diff --git a/backends/bmv2/CMakeLists.txt b/backends/bmv2/CMakeLists.txt index 0002c11757..801a351955 100644 --- a/backends/bmv2/CMakeLists.txt +++ b/backends/bmv2/CMakeLists.txt @@ -63,6 +63,7 @@ set (BMV2_BACKEND_COMMON_HDRS common/action.h common/annotations.h common/backend.h + common/check_unsupported.h common/control.h common/controlFlowGraph.h common/deparser.h diff --git a/backends/bmv2/common/check_unsupported.h b/backends/bmv2/common/check_unsupported.h new file mode 100644 index 0000000000..f8601dc8e5 --- /dev/null +++ b/backends/bmv2/common/check_unsupported.h @@ -0,0 +1,40 @@ +/* +Copyright 2013-present Barefoot Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#ifndef BACKENDS_BMV2_COMMON_CHECK_UNSUPPORTED_H_ +#define BACKENDS_BMV2_COMMON_CHECK_UNSUPPORTED_H_ + +#include "frontends/common/options.h" +#include "ir/ir.h" +#include "lower.h" +#include "midend/convertEnums.h" + +namespace BMV2 { + +class CheckUnsupported : public Inspector { + bool preorder(const IR::ForStatement *fs) override { + error(ErrorType::ERR_UNSUPPORTED, "%sBMV2 does not support loops", fs->srcInfo); + return false; + } + bool preorder(const IR::ForInStatement *fs) override { + error(ErrorType::ERR_UNSUPPORTED, "%sBMV2 does not support loops", fs->srcInfo); + return false; + } +}; + +} // namespace BMV2 + +#endif /* BACKENDS_BMV2_COMMON_CHECK_UNSUPPORTED_H_ */ diff --git a/backends/bmv2/psa_switch/midend.cpp b/backends/bmv2/psa_switch/midend.cpp index 39ba546fc1..f782342be3 100644 --- a/backends/bmv2/psa_switch/midend.cpp +++ b/backends/bmv2/psa_switch/midend.cpp @@ -16,6 +16,7 @@ limitations under the License. #include "midend.h" +#include "backends/bmv2/common/check_unsupported.h" #include "backends/bmv2/psa_switch/options.h" #include "frontends/common/constantFolding.h" #include "frontends/common/resolveReferences/resolveReferences.h" @@ -107,6 +108,7 @@ PsaSwitchMidEnd::PsaSwitchMidEnd(CompilerOptions &options, std::ostream *outStre if (BMV2::PsaSwitchContext::get().options().loadIRFromJson == false) { addPasses({ options.ndebug ? new P4::RemoveAssertAssume(&refMap, &typeMap) : nullptr, + new CheckUnsupported(), new P4::RemoveMiss(&refMap, &typeMap), new P4::EliminateNewtype(&refMap, &typeMap), new P4::EliminateInvalidHeaders(&refMap, &typeMap), @@ -167,6 +169,7 @@ PsaSwitchMidEnd::PsaSwitchMidEnd(CompilerOptions &options, std::ostream *outStre addPasses({ new P4::ResolveReferences(&refMap), new P4::TypeChecking(&refMap, &typeMap), + new CheckUnsupported(), fillEnumMap, [this, fillEnumMap]() { enumMap = fillEnumMap->repr; }, evaluator, diff --git a/backends/bmv2/simple_switch/midend.cpp b/backends/bmv2/simple_switch/midend.cpp index 11b0aae889..e07d23fdd5 100644 --- a/backends/bmv2/simple_switch/midend.cpp +++ b/backends/bmv2/simple_switch/midend.cpp @@ -16,6 +16,7 @@ limitations under the License. #include "midend.h" +#include "backends/bmv2/common/check_unsupported.h" #include "backends/bmv2/simple_switch/options.h" #include "frontends/common/constantFolding.h" #include "frontends/common/resolveReferences/resolveReferences.h" @@ -75,6 +76,7 @@ SimpleSwitchMidEnd::SimpleSwitchMidEnd(CompilerOptions &options, std::ostream *o addPasses( {options.ndebug ? new P4::RemoveAssertAssume(&refMap, &typeMap) : nullptr, new P4::CheckTableSize(), + new CheckUnsupported(), new P4::RemoveMiss(&refMap, &typeMap), new P4::EliminateNewtype(&refMap, &typeMap), new P4::EliminateInvalidHeaders(&refMap, &typeMap), diff --git a/backends/p4test/midend.cpp b/backends/p4test/midend.cpp index a6796e4fea..050595a99a 100644 --- a/backends/p4test/midend.cpp +++ b/backends/p4test/midend.cpp @@ -60,6 +60,7 @@ limitations under the License. #include "midend/simplifySelectCases.h" #include "midend/simplifySelectList.h" #include "midend/tableHit.h" +#include "midend/unrollLoops.h" namespace P4Test { @@ -81,6 +82,7 @@ MidEnd::MidEnd(CompilerOptions &options, std::ostream *outStream) { setName("MidEnd"); auto v1controls = new std::set(); + auto defUse = new P4::ComputeDefUse; addPasses( {options.ndebug ? new P4::RemoveAssertAssume(&refMap, &typeMap) : nullptr, @@ -125,7 +127,14 @@ MidEnd::MidEnd(CompilerOptions &options, std::ostream *outStream) { new P4::EliminateSwitch(&refMap, &typeMap), new P4::ResolveReferences(&refMap), new P4::TypeChecking(&refMap, &typeMap, true), // update types before ComputeDefUse - new P4::ComputeDefUse, // present for testing + new PassRepeated({ + defUse, + new P4::UnrollLoops(refMap, defUse), + new P4::LocalCopyPropagation(&refMap, &typeMap), + new P4::ConstantFolding(&refMap, &typeMap), + new P4::StrengthReduction(&refMap, &typeMap), + }), + new P4::MoveDeclarations(), // more may have been introduced evaluator, [v1controls, evaluator](const IR::Node *root) -> const IR::Node * { auto toplevel = evaluator->getToplevelBlock(); diff --git a/frontends/p4/def_use.cpp b/frontends/p4/def_use.cpp index efab7c5f16..8163202fca 100644 --- a/frontends/p4/def_use.cpp +++ b/frontends/p4/def_use.cpp @@ -253,6 +253,15 @@ bool LocationSet::overlaps(const LocationSet *other) const { return false; } +bool LocationSet::operator==(const LocationSet &other) const { + auto it = other.begin(); + for (auto s : locations) { + if (it == other.end() || *it != s) return false; + ++it; + } + return it == other.end(); +} + void ProgramPoints::add(const ProgramPoints *from) { points.insert(from->points.begin(), from->points.end()); } @@ -406,7 +415,7 @@ void ComputeWriteSet::enterScope(const IR::ParameterList *parameters, } } } - allDefinitions->setDefinitionsAt(entryPoint, defs, false); + allDefinitions->setDefinitionsAt(entryPoint, defs, true); currentDefinitions = defs; if (LOGGING(5)) LOG5("CWS Entered scope " << entryPoint << " definitions are " << Log::endl << defs); @@ -460,6 +469,9 @@ bool ComputeWriteSet::setDefinitions(Definitions *defs, const IR::Node *node, bo // overwriting always in parser states. In this case we actually expect // that the definitions are monotonically increasing. if (findContext()) overwrite = true; + // Loop bodies get visited repeatedly until a fixed point, so we likewise + // expect monotonically increasing write sets. + if (continueDefinitions != nullptr) overwrite = true; // in a loop allDefinitions->setDefinitionsAt(point, currentDefinitions, overwrite); if (LOGGING(5)) LOG5("CWS Definitions at " << point << " are " << Log::endl << defs); @@ -820,6 +832,69 @@ bool ComputeWriteSet::preorder(const IR::IfStatement *statement) { return setDefinitions(result); } +bool ComputeWriteSet::preorder(const IR::ForStatement *statement) { + LOG3("CWS Visiting " << dbp(statement)); + if (currentDefinitions->isUnreachable()) return setDefinitions(currentDefinitions); + visit(statement->init, "init"); + + auto saveBreak = breakDefinitions; + auto saveContinue = continueDefinitions; + breakDefinitions = new Definitions(); + continueDefinitions = new Definitions(); + Definitions *startDefs = nullptr; + Definitions *exitDefs = nullptr; + + do { + startDefs = currentDefinitions; + visit(statement->condition, "condition"); + auto cond = getWrites(statement->condition); + // exitDefs are the definitions after evaluating the condition + exitDefs = currentDefinitions->writes(getProgramPoint(), cond); + (void)setDefinitions(exitDefs, statement->condition, true); + visit(statement->body, "body"); + currentDefinitions = currentDefinitions->joinDefinitions(continueDefinitions); + visit(statement->updates, "updates"); + currentDefinitions = currentDefinitions->joinDefinitions(startDefs); + } while (!(*startDefs == *currentDefinitions)); + + exitDefs = exitDefs->joinDefinitions(breakDefinitions); + breakDefinitions = saveBreak; + continueDefinitions = saveContinue; + return setDefinitions(exitDefs); +} + +bool ComputeWriteSet::preorder(const IR::ForInStatement *statement) { + LOG3("CWS Visiting " << dbp(statement)); + if (currentDefinitions->isUnreachable()) return setDefinitions(currentDefinitions); + visit(statement->collection, "collection"); + + auto saveBreak = breakDefinitions; + auto saveContinue = continueDefinitions; + breakDefinitions = new Definitions(); + continueDefinitions = new Definitions(); + Definitions *startDefs = nullptr; + Definitions *exitDefs = currentDefinitions; // in case collection is empty; + + do { + startDefs = currentDefinitions; + lhs = true; + visit(statement->ref, "ref"); + lhs = false; + auto cond = getWrites(statement->ref); + auto defs = currentDefinitions->writes(getProgramPoint(), cond); + (void)setDefinitions(defs, statement->ref, true); + visit(statement->body, "body"); + currentDefinitions = currentDefinitions->joinDefinitions(continueDefinitions); + currentDefinitions = currentDefinitions->joinDefinitions(startDefs); + } while (!(*startDefs == *currentDefinitions)); + + exitDefs = exitDefs->joinDefinitions(currentDefinitions); + exitDefs = exitDefs->joinDefinitions(breakDefinitions); + breakDefinitions = saveBreak; + continueDefinitions = saveContinue; + return setDefinitions(exitDefs); +} + bool ComputeWriteSet::preorder(const IR::BlockStatement *statement) { if (currentDefinitions->isUnreachable()) return setDefinitions(currentDefinitions); visit(statement->components, "components"); @@ -827,27 +902,35 @@ bool ComputeWriteSet::preorder(const IR::BlockStatement *statement) { } bool ComputeWriteSet::preorder(const IR::ReturnStatement *statement) { + if (currentDefinitions->isUnreachable()) return setDefinitions(currentDefinitions); if (statement->expression != nullptr) visit(statement->expression); - returnedDefinitions = returnedDefinitions->joinDefinitions(currentDefinitions); - if (LOGGING(5)) - LOG5("Return definitions " << returnedDefinitions); - else - LOG3("Return " << returnedDefinitions->size() << " definitions"); - auto defs = currentDefinitions->cloneDefinitions(); - defs->setUnreachable(); - return setDefinitions(defs); + return handleJump("Return", returnedDefinitions); } bool ComputeWriteSet::preorder(const IR::ExitStatement *) { if (currentDefinitions->isUnreachable()) return setDefinitions(currentDefinitions); - exitDefinitions = exitDefinitions->joinDefinitions(currentDefinitions); + return handleJump("Exit", exitDefinitions); +} + +bool ComputeWriteSet::preorder(const IR::BreakStatement *) { + if (currentDefinitions->isUnreachable()) return setDefinitions(currentDefinitions); + return handleJump("Break", breakDefinitions); +} + +bool ComputeWriteSet::preorder(const IR::ContinueStatement *) { + if (currentDefinitions->isUnreachable()) return setDefinitions(currentDefinitions); + return handleJump("Continue", continueDefinitions); +} + +bool ComputeWriteSet::handleJump(const char *tok, Definitions *&defs) { + defs = defs->joinDefinitions(currentDefinitions); if (LOGGING(5)) - LOG5("Exit definitions " << exitDefinitions); + LOG5(tok << " definitions " << defs); else - LOG3("Exit with " << exitDefinitions->size() << " definitions"); - auto defs = currentDefinitions->cloneDefinitions(); - defs->setUnreachable(); - return setDefinitions(defs); + LOG3(tok << " with " << defs->size() << " definitions"); + auto after = currentDefinitions->cloneDefinitions(); + after->setUnreachable(); + return setDefinitions(after); } bool ComputeWriteSet::preorder(const IR::EmptyStatement *) { diff --git a/frontends/p4/def_use.h b/frontends/p4/def_use.h index b21dd68e26..4cc8056ffa 100644 --- a/frontends/p4/def_use.h +++ b/frontends/p4/def_use.h @@ -231,6 +231,7 @@ class LocationSet : public IHasDbPrint { } // only defined for canonical representations bool overlaps(const LocationSet *other) const; + bool operator==(const LocationSet &other) const; bool isEmpty() const { return locations.empty(); } }; @@ -476,10 +477,12 @@ class AllDefinitions : public IHasDbPrint { class ComputeWriteSet : public Inspector, public IHasDbPrint { protected: - AllDefinitions *allDefinitions; /// Result computed by this pass. - Definitions *currentDefinitions; /// Before statement currently processed. - Definitions *returnedDefinitions; /// Definitions after return statements. - Definitions *exitDefinitions; /// Definitions after exit statements. + AllDefinitions *allDefinitions; /// Result computed by this pass. + Definitions *currentDefinitions; /// Before statement currently processed. + Definitions *returnedDefinitions; /// Definitions after return statements. + Definitions *exitDefinitions; /// Definitions after exit statements. + Definitions *breakDefinitions = nullptr; /// Definitions at break statements. + Definitions *continueDefinitions = nullptr; /// Definitions at continue statements. ProgramPoint callingContext; const StorageMap *storageMap; /// if true we are processing an expression on the lhs of an assignment @@ -498,6 +501,8 @@ class ComputeWriteSet : public Inspector, public IHasDbPrint { currentDefinitions(definitions), returnedDefinitions(nullptr), exitDefinitions(source->exitDefinitions), + breakDefinitions(source->breakDefinitions), + continueDefinitions(source->continueDefinitions), callingContext(context), storageMap(source->storageMap), lhs(false), @@ -522,9 +527,12 @@ class ComputeWriteSet : public Inspector, public IHasDbPrint { CHECK_NULL(expression); CHECK_NULL(loc); LOG3(expression << dbp(expression) << " writes " << loc); - BUG_CHECK(writes.find(expression) == writes.end() || expression->is(), - "Expression %1% write set already set", expression); - writes.emplace(expression, loc); + if (auto it = writes.find(expression); it != writes.end()) { + BUG_CHECK(*it->second == *loc || expression->is(), + "Expression %1% write set already set", expression); + } else { + writes.emplace(expression, loc); + } } void dbprint(std::ostream &out) const override { if (writes.empty()) out << "No writes"; @@ -589,7 +597,12 @@ class ComputeWriteSet : public Inspector, public IHasDbPrint { bool preorder(const IR::AssignmentStatement *statement) override; bool preorder(const IR::ReturnStatement *statement) override; bool preorder(const IR::ExitStatement *statement) override; + bool preorder(const IR::BreakStatement *statement) override; + bool handleJump(const char *tok, Definitions *&defs); + bool preorder(const IR::ContinueStatement *statement) override; bool preorder(const IR::IfStatement *statement) override; + bool preorder(const IR::ForStatement *statement) override; + bool preorder(const IR::ForInStatement *statement) override; bool preorder(const IR::BlockStatement *statement) override; bool preorder(const IR::SwitchStatement *statement) override; bool preorder(const IR::EmptyStatement *statement) override; diff --git a/frontends/p4/removeReturns.cpp b/frontends/p4/removeReturns.cpp index bdcdfed96f..d1fde2a731 100644 --- a/frontends/p4/removeReturns.cpp +++ b/frontends/p4/removeReturns.cpp @@ -127,14 +127,15 @@ const IR::Node *DoRemoveReturns::preorder(IR::ReturnStatement *statement) { set(TernaryBool::Yes); auto vec = new IR::IndexedVector(); - auto left = new IR::PathExpression(returnVar); + auto left = new IR::PathExpression(IR::Type::Boolean::get(), returnVar); vec->push_back( new IR::AssignmentStatement(statement->srcInfo, left, new IR::BoolLiteral(true))); if (statement->expression != nullptr) { - left = new IR::PathExpression(returnedValue); + left = new IR::PathExpression(statement->expression->type, returnedValue); vec->push_back( new IR::AssignmentStatement(statement->srcInfo, left, statement->expression)); } + if (findContext()) vec->push_back(new IR::BreakStatement); return new IR::BlockStatement(*vec); } @@ -158,7 +159,7 @@ const IR::Node *DoRemoveReturns::preorder(IR::BlockStatement *statement) { break; } else if (r == TernaryBool::Maybe) { auto newBlock = new IR::BlockStatement; - auto path = new IR::PathExpression(returnVar); + auto path = new IR::PathExpression(IR::Type::Boolean::get(), returnVar); auto condition = new IR::LNot(path); auto ifstat = new IR::IfStatement(condition, newBlock, nullptr); block->push_back(ifstat); @@ -211,4 +212,21 @@ const IR::Node *DoRemoveReturns::preorder(IR::SwitchStatement *statement) { return statement; } +const IR::Node *DoRemoveReturns::postorder(IR::LoopStatement *loop) { + // loop body might not (all) execute, so can't be certain if it returns + if (hasReturned() == TernaryBool::Yes) set(TernaryBool::Maybe); + + // only need to add an extra check for nested loops + if (!findContext()) return loop; + // only if the inner loop may have returned + if (hasReturned() == TernaryBool::No) return loop; + + // break out of the outer loop if the inner loop returned + auto rv = new IR::BlockStatement(); + rv->push_back(loop); + rv->push_back(new IR::IfStatement(new IR::PathExpression(IR::Type::Boolean::get(), returnVar), + new IR::BreakStatement(), nullptr)); + return rv; +} + } // namespace P4 diff --git a/frontends/p4/removeReturns.h b/frontends/p4/removeReturns.h index c51604e086..70e949f9b0 100644 --- a/frontends/p4/removeReturns.h +++ b/frontends/p4/removeReturns.h @@ -98,6 +98,8 @@ class DoRemoveReturns : public Transform { prune(); return parser; } + + const IR::Node *postorder(IR::LoopStatement *loop) override; }; class RemoveReturns : public PassManager { diff --git a/frontends/p4/resetHeaders.cpp b/frontends/p4/resetHeaders.cpp index c7aa51265f..c9adcdce72 100644 --- a/frontends/p4/resetHeaders.cpp +++ b/frontends/p4/resetHeaders.cpp @@ -53,9 +53,11 @@ void DoResetHeaders::generateResets(const TypeMap *typeMap, const IR::Type *type const IR::Node *DoResetHeaders::postorder(IR::Declaration_Variable *decl) { if (decl->initializer != nullptr) return decl; LOG3("DoResetHeaders context " << dbp(getContext()->node)); + auto parent = getContext()->node; + // Don't reset index var in for..in statements. + if (parent->is()) return decl; auto type = typeMap->getType(getOriginal(), true); auto path = new IR::PathExpression(decl->getName()); - auto parent = getContext()->node; // For declarations in parsers and controls we have to insert the // reset in the start state or the body respectively. bool separate = parent->is() || parent->is(); diff --git a/frontends/p4/sideEffects.cpp b/frontends/p4/sideEffects.cpp index 4ad039f3ab..be3a14b511 100644 --- a/frontends/p4/sideEffects.cpp +++ b/frontends/p4/sideEffects.cpp @@ -674,6 +674,36 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::SwitchStatement *statement) return rv; } +const IR::Node *DoSimplifyExpressions::preorder(IR::ForStatement *statement) { + visit(statement->init, "init"); + visit(statement->condition, "condition"); + if (!statements.empty()) { + // FIXME -- in theory could deal with this by duplicating statements here and + // adding them to both init and updates. + error(ErrorType::ERR_INVALID, "%1%Side effects in for condition not supported", + statement->condition->srcInfo); + statements.clear(); + } + visit(statement->body, "body"); + visit(statement->updates, "updates"); + prune(); + return statement; +} + +const IR::Node *DoSimplifyExpressions::preorder(IR::ForInStatement *statement) { + IR::Statement *rv = statement; + visit(statement->decl, "decl"); + visit(statement->collection, "collection"); + if (!statements.empty()) { + statements.push_back(statement); + rv = new IR::BlockStatement(statements); + statements.clear(); + } + visit(statement->body, "body"); + prune(); + return rv; +} + void DoSimplifyExpressions::end_apply(const IR::Node *) { BUG_CHECK(toInsert.empty(), "DoSimplifyExpressions::end_apply orphaned declarations"); BUG_CHECK(statements.empty(), "DoSimplifyExpressions::end_apply orphaned statements"); diff --git a/frontends/p4/sideEffects.h b/frontends/p4/sideEffects.h index c2092a69d5..f8832a1940 100644 --- a/frontends/p4/sideEffects.h +++ b/frontends/p4/sideEffects.h @@ -243,6 +243,8 @@ class DoSimplifyExpressions : public Transform, P4WriteContext { const IR::Node *postorder(IR::ReturnStatement *statement) override; const IR::Node *preorder(IR::SwitchStatement *statement) override; const IR::Node *preorder(IR::IfStatement *statement) override; + const IR::Node *preorder(IR::ForStatement *statement) override; + const IR::Node *preorder(IR::ForInStatement *statement) override; void end_apply(const IR::Node *) override; }; diff --git a/frontends/p4/simplifyDefUse.cpp b/frontends/p4/simplifyDefUse.cpp index fe914dbac3..85eb04d1ee 100644 --- a/frontends/p4/simplifyDefUse.cpp +++ b/frontends/p4/simplifyDefUse.cpp @@ -948,6 +948,26 @@ class FindUninitialized : public Inspector { return setCurrent(statement); } + bool preorder(const IR::ForInStatement *statement) override { + Log::TempIndent indent; + LOG3("FU Visiting " << dbp(statement) << " " << statement << indent); + if (!unreachable) { + visit(statement->collection, "collection"); + lhs = true; + visit(statement->decl, "decl"); + visit(statement->ref, "ref"); + for (auto *l : *headerDefs->getStorageLocation(statement->ref)) + headerDefs->setValueToStorage(l, TernaryBool::Yes); + lhs = false; + currentPoint.assign(context, statement->ref); + visit(statement->body); + unreachable = false; + } else { + LOG3("Unreachable"); + } + return setCurrent(statement); + } + ////////////////// Expressions bool preorder(const IR::Literal *expression) override { diff --git a/frontends/p4/toP4/toP4.cpp b/frontends/p4/toP4/toP4.cpp index 94adc28f98..a6d312571a 100644 --- a/frontends/p4/toP4/toP4.cpp +++ b/frontends/p4/toP4/toP4.cpp @@ -1131,6 +1131,20 @@ bool ToP4::preorder(const IR::BlockStatement *s) { return false; } +bool ToP4::preorder(const IR::BreakStatement *) { + dump(1); + builder.append("break"); + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::ContinueStatement *) { + dump(1); + builder.append("continue"); + builder.endOfStatement(); + return false; +} + bool ToP4::preorder(const IR::ExitStatement *) { dump(1); builder.append("exit"); @@ -1192,6 +1206,80 @@ bool ToP4::preorder(const IR::IfStatement *s) { return false; } +bool ToP4::preorder(const IR::ForStatement *s) { + dump(2); + if (!s->annotations->annotations.empty()) { + visit(s->annotations); + builder.spc(); + } + builder.append("for ("); + bool first = true; + for (auto *d : s->init) { + if (!first) builder.append(", "); + builder.supressStatementSemi(); + visit(d, "init"); + first = false; + } + builder.append("; "); + visit(s->condition, "condition"); + builder.append("; "); + first = true; + for (auto *e : s->updates) { + if (e->is()) continue; + if (!first) builder.append(", "); + builder.supressStatementSemi(); + visit(e, "updates"); + first = false; + } + builder.append(") "); + if (!s->body->is()) { + builder.append("{"); + builder.increaseIndent(); + builder.newline(); + builder.emitIndent(); + } + visit(s->body, "body"); + if (!s->body->is()) { + builder.newline(); + builder.decreaseIndent(); + builder.emitIndent(); + builder.append("}"); + } + return false; +} + +bool ToP4::preorder(const IR::ForInStatement *s) { + dump(2); + if (!s->annotations->annotations.empty()) { + visit(s->annotations); + builder.spc(); + } + builder.append("for ("); + if (s->decl) { + builder.supressStatementSemi(); + visit(s->decl, "decl"); + } else { + visit(s->ref, "ref"); + } + builder.append(" in "); + visit(s->collection); + builder.append(") "); + if (!s->body->is()) { + builder.append("{"); + builder.increaseIndent(); + builder.newline(); + builder.emitIndent(); + } + visit(s->body, "body"); + if (!s->body->is()) { + builder.newline(); + builder.decreaseIndent(); + builder.emitIndent(); + builder.append("}"); + } + return false; +} + bool ToP4::preorder(const IR::MethodCallStatement *s) { dump(3); visit(s->methodCall); diff --git a/frontends/p4/toP4/toP4.h b/frontends/p4/toP4/toP4.h index eb4f82398c..2541022c7d 100644 --- a/frontends/p4/toP4/toP4.h +++ b/frontends/p4/toP4/toP4.h @@ -230,10 +230,14 @@ class ToP4 : public Inspector { bool preorder(const IR::MethodCallStatement *s) override; bool preorder(const IR::EmptyStatement *s) override; bool preorder(const IR::ReturnStatement *s) override; + bool preorder(const IR::BreakStatement *s) override; + bool preorder(const IR::ContinueStatement *s) override; bool preorder(const IR::ExitStatement *s) override; bool preorder(const IR::SwitchCase *s) override; bool preorder(const IR::SwitchStatement *s) override; bool preorder(const IR::IfStatement *s) override; + bool preorder(const IR::ForStatement *s) override; + bool preorder(const IR::ForInStatement *s) override; // misc bool preorder(const IR::NamedExpression *ne) override; diff --git a/frontends/p4/typeChecking/typeChecker.cpp b/frontends/p4/typeChecking/typeChecker.cpp index 4ca4ab26c6..0b0529fd0d 100644 --- a/frontends/p4/typeChecking/typeChecker.cpp +++ b/frontends/p4/typeChecking/typeChecker.cpp @@ -2754,6 +2754,10 @@ const IR::Node *TypeInference::typeSet(const IR::Operation_Binary *expression) { } else { // both are InfInt: use same exact type for both sides, so it is properly // set after unification + // FIXME -- the below is obviously wrong and just serves to tweak when precisely + // the type will be inferred -- papering over bugs elsewhere in typechecking, + // avoiding the BUG_CHECK(!readOnly... in end_apply/apply_visitor above. + // (maybe just need learner->readOnly = false in TypeInference::learn above?) auto r = expression->right->clone(); auto e = expression->clone(); if (isCompileTimeConstant(expression->right)) setCompileTimeConstant(r); @@ -4149,6 +4153,40 @@ const IR::Node *TypeInference::postorder(IR::AssignmentStatement *assign) { return assign; } +const IR::Node *TypeInference::postorder(IR::ForInStatement *forin) { + LOG3("TI Visiting " << dbp(getOriginal())); + auto ltype = getType(forin->ref); + if (ltype == nullptr) return forin; + auto ctype = getType(forin->collection); + if (ctype == nullptr) return forin; + + if (!isLeftValue(forin->ref)) { + typeError("Expression %1% cannot be the target of an assignment", forin->ref); + LOG2(forin->ref); + return forin; + } + if (auto range = forin->collection->to()) { + auto rclone = range->clone(); + rclone->left = assignment(forin, ltype, rclone->left); + rclone->right = assignment(forin, ltype, rclone->right); + if (*range != *rclone) + forin->collection = rclone; + else + delete rclone; + } else if (auto *stack = ctype->to()) { + if (!canCastBetween(stack->elementType, ltype)) + typeError("%1% does not match header stack type %2%", forin->ref, ctype); + } else if (auto *list = ctype->to()) { + if (!canCastBetween(list->elementType, ltype)) + typeError("%1% does not match %2% element type", forin->ref, ctype); + } else { + error(ErrorType::ERR_UNSUPPORTED, + "%1%Typechecking does not support iteration over this collection of type %2%", + forin->collection->srcInfo, ctype); + } + return forin; +} + const IR::Node *TypeInference::postorder(IR::ActionListElement *elem) { if (done()) return elem; auto type = getType(elem->expression); diff --git a/frontends/p4/typeChecking/typeChecker.h b/frontends/p4/typeChecking/typeChecker.h index 7af76204b4..1980e26818 100644 --- a/frontends/p4/typeChecking/typeChecker.h +++ b/frontends/p4/typeChecking/typeChecker.h @@ -331,6 +331,7 @@ class TypeInference : public Transform { const IR::Node *postorder(IR::IfStatement *stat) override; const IR::Node *postorder(IR::SwitchStatement *stat) override; const IR::Node *postorder(IR::AssignmentStatement *stat) override; + const IR::Node *postorder(IR::ForInStatement *stat) override; const IR::Node *postorder(IR::ActionListElement *elem) override; const IR::Node *postorder(IR::KeyElement *elem) override; const IR::Node *postorder(IR::Property *elem) override; diff --git a/frontends/p4/validateParsedProgram.cpp b/frontends/p4/validateParsedProgram.cpp index b54be62493..d301865004 100644 --- a/frontends/p4/validateParsedProgram.cpp +++ b/frontends/p4/validateParsedProgram.cpp @@ -251,4 +251,17 @@ void ValidateParsedProgram::postorder(const IR::Dots *dots) { } } +/// Check that continue and break statements are only used in the context of a for statement. +void ValidateParsedProgram::postorder(const IR::BreakStatement *s) { + if (!findContext() && !findContext()) + ::error(ErrorType::ERR_INVALID, + "%1%: break statement must be used in the context of a for statement.", s); +} + +void ValidateParsedProgram::postorder(const IR::ContinueStatement *s) { + if (!findContext() && !findContext()) + ::error(ErrorType::ERR_INVALID, + "%1%: continue statement must be used in the context of a for statement.", s); +} + } // namespace P4 diff --git a/frontends/p4/validateParsedProgram.h b/frontends/p4/validateParsedProgram.h index cbb705c325..22f8955869 100644 --- a/frontends/p4/validateParsedProgram.h +++ b/frontends/p4/validateParsedProgram.h @@ -47,6 +47,7 @@ namespace P4 { - names of all parameters are distinct - no duplicate declarations in toplevel program - Dots are the last field + - continue and break statements are only used in the context of a for statement */ class ValidateParsedProgram final : public Inspector { void container(const IR::IContainer *type); @@ -89,6 +90,8 @@ class ValidateParsedProgram final : public Inspector { parser->getConstructorParameters()); } void postorder(const IR::Dots *dots) override; + void postorder(const IR::BreakStatement *s) override; + void postorder(const IR::ContinueStatement *s) override; }; } // namespace P4 diff --git a/frontends/parsers/p4/p4lexer.ll b/frontends/parsers/p4/p4lexer.ll index d214459d45..78bad60e35 100644 --- a/frontends/parsers/p4/p4lexer.ll +++ b/frontends/parsers/p4/p4lexer.ll @@ -115,8 +115,12 @@ using Parser = P4::P4Parser; return makeToken(BOOL); } "bit" { BEGIN(driver.saveState); driver.template_args = true; return makeToken(BIT); } +"break" { BEGIN(driver.saveState); driver.template_args = false; + return makeToken(BREAK); } "const" { BEGIN(driver.saveState); driver.template_args = false; return makeToken(CONST); } +"continue" { BEGIN(driver.saveState); driver.template_args = false; + return makeToken(CONTINUE); } "control" { BEGIN(driver.saveState); driver.template_args = false; return makeToken(CONTROL); } "default" { BEGIN(driver.saveState); driver.template_args = false; @@ -135,6 +139,8 @@ using Parser = P4::P4Parser; return makeToken(EXTERN); } "false" { BEGIN(driver.saveState); driver.template_args = false; return makeToken(FALSE); } +"for" { BEGIN(driver.saveState); driver.template_args = false; + return makeToken(FOR); } "header" { BEGIN(driver.saveState); driver.template_args = false; return makeToken(HEADER); } "header_union" { BEGIN(driver.saveState); driver.template_args = false; diff --git a/frontends/parsers/p4/p4parser.ypp b/frontends/parsers/p4/p4parser.ypp index ef2c624330..980c2e1876 100644 --- a/frontends/parsers/p4/p4parser.ypp +++ b/frontends/parsers/p4/p4parser.ypp @@ -227,8 +227,8 @@ inline std::ostream& operator<<(std::ostream& out, const P4::Token& t) { %token DOTS "..." %token RANGE ".." %token TRUE FALSE THIS -%token ABSTRACT ACTION ACTIONS APPLY BOOL BIT CONST CONTROL DEFAULT - ELSE ENTRIES ENUM ERROR EXIT EXTERN HEADER HEADER_UNION IF IN INOUT +%token ABSTRACT ACTION ACTIONS APPLY BOOL BIT BREAK CONST CONTINUE CONTROL DEFAULT + ELSE ENTRIES ENUM ERROR EXIT EXTERN FOR HEADER HEADER_UNION IF IN INOUT INT KEY LIST SELECT MATCH_KIND TYPE OUT PACKAGE PARSER PRAGMA PRIORITY RETURN STATE STRING STRUCT SWITCH TABLE TRANSITION TUPLE TYPEDEF VARBIT VALUESET VOID @@ -247,7 +247,7 @@ inline std::ostream& operator<<(std::ostream& out, const P4::Token& t) { stateExpression optInitializer initializer simpleKeysetExpression transitionStatement switchLabel p4rtControllerType reducedSimpleKeysetExpression entryPriority - nonBraceExpression + nonBraceExpression forCollectionExpr %type baseType typeOrVoid specializedType headerStackType typeRef tupleType typeArg realTypeArg namedType p4listType %type typeName @@ -270,19 +270,23 @@ inline std::ostream& operator<<(std::ostream& out, const P4::Token& t) { %type statement emptyStatement returnStatement switchStatement exitStatement assignmentOrMethodCallStatement conditionalStatement + assignmentOrMethodCallStatementWithoutSemicolon directApplication + forStatement breakStatement continueStatement %type blockStatement parserBlockStatement controlBody objInitializer %type statementOrDeclaration parserStatement -%type*> objDeclarations statOrDeclList - parserStatements + declOrAssignmentOrMethodCallStatement +%type*> objDeclarations statOrDeclList parserStatements + forInitStatements forInitStatementsNonEmpty + forUpdateStatements forUpdateStatementsNonEmpty %type switchCase %type*> switchCases %type*> typeArgumentList realTypeArgumentList %type parserState %type*> parserStates %type constantDeclaration actionDeclaration - variableDeclaration instantiation functionDeclaration + variableDeclaration variableDeclarationWithoutSemicolon instantiation functionDeclaration objDeclaration tableDeclaration controlLocalDeclaration parserLocalElement valueSetDeclaration %type headerTypeDeclaration structTypeDeclaration @@ -558,7 +562,9 @@ annotationToken | APPLY { $$ = $1; } | BOOL { $$ = $1; } | BIT { $$ = $1; } + | BREAK { $$ = $1; } | CONST { $$ = $1; } + | CONTINUE { $$ = $1; } | CONTROL { $$ = $1; } | DEFAULT { $$ = $1; } | ELSE { $$ = $1; } @@ -568,6 +574,7 @@ annotationToken | EXIT { $$ = $1; } | EXTERN { $$ = $1; } | FALSE { $$ = $1; } + | FOR { $$ = $1; } | HEADER { $$ = $1; } | HEADER_UNION { $$ = $1; } | IF { $$ = $1; } @@ -1180,18 +1187,22 @@ typedefDeclaration /*************************** STATEMENTS *************************/ assignmentOrMethodCallStatement + : assignmentOrMethodCallStatementWithoutSemicolon ";" { $$ = $1; } + ; + +assignmentOrMethodCallStatementWithoutSemicolon // These rules are overly permissive, but they avoid some conflicts - : lvalue "(" argumentList ")" ";" + : lvalue "(" argumentList ")" { auto mc = new IR::MethodCallExpression(@1 + @4, $1, new IR::Vector(), $3); $$ = new IR::MethodCallStatement(@1 + @4, mc); } - | lvalue l_angle typeArgumentList r_angle "(" argumentList ")" ";" + | lvalue l_angle typeArgumentList r_angle "(" argumentList ")" { auto mc = new IR::MethodCallExpression(@1 + @7, $1, $3, $6); $$ = new IR::MethodCallStatement(@1 + @7, mc); } - | lvalue "=" expression ";" + | lvalue "=" expression { $$ = new IR::AssignmentStatement(@2, $1, $3); } ; @@ -1216,6 +1227,14 @@ conditionalStatement { $$ = new IR::IfStatement(@1, $3, $5, $7); } ; +breakStatement + : BREAK ";" { $$ = new IR::BreakStatement(@1); } + ; + +continueStatement + : CONTINUE ";" { $$ = new IR::ContinueStatement(@1); } + ; + // To support direct invocation of a control or parser without instantiation directApplication : typeName "." APPLY "(" argumentList ")" ";" { @@ -1237,8 +1256,11 @@ statement | emptyStatement { $$ = $1; } | blockStatement { $$ = $1; } | returnStatement { $$ = $1; } + | breakStatement { $$ = $1; } + | continueStatement { $$ = $1; } | exitStatement { $$ = $1; } | switchStatement { $$ = $1; } + | forStatement { $$ = $1; } ; blockStatement @@ -1283,6 +1305,53 @@ statementOrDeclaration | instantiation { $$ = $1; } ; +forStatement + : optAnnotations FOR "(" forInitStatements ";" + expression ";" + forUpdateStatements ")" + statement + { $$ = new IR::ForStatement(@2+@9, *$4, $6, *$8, $10); } + | optAnnotations FOR "(" typeRef name IN forCollectionExpr ")" statement + { auto decl = new IR::Declaration_Variable(@4+@5, *$5, $4); + $$ = new IR::ForInStatement(@2+@7, $1, decl, $7, $9); } + | optAnnotations FOR "(" prefixedNonTypeName IN forCollectionExpr ")" statement + { $$ = new IR::ForInStatement(@2+@7, $1, new IR::PathExpression(@4, $4), $6, $8); } + ; + +forInitStatements + : %empty { $$ = new IR::IndexedVector(); } + | forInitStatementsNonEmpty { $$ = $1; } + ; + +forInitStatementsNonEmpty + : declOrAssignmentOrMethodCallStatement { $$ = new IR::IndexedVector($1); } + | forInitStatementsNonEmpty "," declOrAssignmentOrMethodCallStatement { + ($$ = $1)->push_back($3); } + ; + +declOrAssignmentOrMethodCallStatement + : variableDeclarationWithoutSemicolon { $$ = $1; } + | assignmentOrMethodCallStatementWithoutSemicolon { $$ = $1; } + ; + +forUpdateStatements + : %empty { $$ = new IR::IndexedVector(); } + | forUpdateStatementsNonEmpty { $$ = $1; } + ; + +forUpdateStatementsNonEmpty + : assignmentOrMethodCallStatementWithoutSemicolon { + $$ = new IR::IndexedVector($1); } + | forUpdateStatementsNonEmpty "," assignmentOrMethodCallStatementWithoutSemicolon { + ($$ = $1)->push_back($3); } + ; + +forCollectionExpr + : expression { $$ = $1; } + | expression ".." expression { $$ = new IR::Range(@1 + @3, $1, $3); } + | typeRef { $$ = new IR::ConstructorCallExpression(@1, $1, {}); } + ; + /************************* TABLE *********************************/ tableDeclaration @@ -1386,12 +1455,16 @@ actionDeclaration /************************* VARIABLES *****************************/ variableDeclaration - : annotations typeRef name optInitializer ";" + : variableDeclarationWithoutSemicolon ";" { $$ = $1; } + ; + +variableDeclarationWithoutSemicolon + : annotations typeRef name optInitializer { auto ann = new IR::Annotations(@1, *$1); $$ = new IR::Declaration_Variable(@1+@4, *$3, ann, $2, $4); driver.structure->declareObject(*$3, $2->toString()); } - | typeRef name optInitializer ";" - { $$ = new IR::Declaration_Variable(@1+@4, *$2, $1, $3); + | typeRef name optInitializer + { $$ = new IR::Declaration_Variable(@1+@3, *$2, $1, $3); driver.structure->declareObject(*$2, $1->toString()); } ; diff --git a/ir/CMakeLists.txt b/ir/CMakeLists.txt index 8ab76e9b81..bdce1d6aac 100644 --- a/ir/CMakeLists.txt +++ b/ir/CMakeLists.txt @@ -25,6 +25,7 @@ set (IR_SRCS ir.cpp irutils.cpp json_parser.cpp + loop-visitor.cpp node.cpp pass_manager.cpp pass_utils.cpp diff --git a/ir/dbprint-stmt.cpp b/ir/dbprint-stmt.cpp index f04a002661..52a8800c04 100644 --- a/ir/dbprint-stmt.cpp +++ b/ir/dbprint-stmt.cpp @@ -84,3 +84,34 @@ void IR::SwitchStatement::dbprint(std::ostream &out) const { } out << unindent << " }" << setprec(prec); } + +void IR::ForStatement::dbprint(std::ostream &out) const { + int prec = getprec(out); + out << Prec_Low << "for ("; + bool first = true; + for (auto *sd : init) { + if (!first) out << ", "; + out << sd; + first = false; + } + out << "; " << condition << "; "; + first = true; + for (auto *sd : updates) { + if (!first) out << ", "; + out << sd; + first = false; + } + out << ") {" << indent << Log::endl << body << " }" << unindent << setprec(prec); +} + +void IR::ForInStatement::dbprint(std::ostream &out) const { + int prec = getprec(out); + out << Prec_Low << "for ("; + if (decl) { + out << decl; + } else { + out << ref; + } + out << " in " << collection << ") {" << indent << Log::endl + << body << " }" << unindent << setprec(prec); +} diff --git a/ir/expression.def b/ir/expression.def index 596c2f1dbc..2ae587fd2b 100644 --- a/ir/expression.def +++ b/ir/expression.def @@ -282,6 +282,7 @@ class StringLiteral : Literal { class PathExpression : Expression { Path path; PathExpression { if (!srcInfo && path) srcInfo = path->srcInfo; } + PathExpression(Type t, IR::ID id) : Expression(id.srcInfo, t), path(new IR::Path(id)) {} PathExpression(IR::ID id) : Expression(id.srcInfo), path(new IR::Path(id)) {} toString{ return path->toString(); } } diff --git a/ir/ir.cpp b/ir/ir.cpp index 36f23f864e..93cab1f2f6 100644 --- a/ir/ir.cpp +++ b/ir/ir.cpp @@ -212,6 +212,25 @@ const Type_Method *P4Table::getApplyMethodType() const { const Type_Method *Type_Table::getApplyMethodType() const { return table->getApplyMethodType(); } +void BlockStatement::append(const StatOrDecl *stmt) { + srcInfo += stmt->srcInfo; + if (auto bs = stmt->to()) { + bool merge = true; + for (auto annot : bs->annotations->annotations) { + auto a = annotations->getSingle(annot->name); + if (!a || !a->equiv(*annot)) { + merge = false; + break; + } + } + if (merge) { + components.append(bs->components); + return; + } + } + components.push_back(stmt); +} + void Block::setValue(const Node *node, const CompileTimeValue *value) { CHECK_NULL(node); auto it = constantValue.find(node); diff --git a/ir/ir.def b/ir/ir.def index 6bef519624..bc24cc504a 100644 --- a/ir/ir.def +++ b/ir/ir.def @@ -422,7 +422,9 @@ class P4Program : IGeneralNamespace { ///////////////////////////// Statements ////////////////////////// -abstract Statement : StatOrDecl {} +abstract Statement : StatOrDecl { +#apply +} class ExitStatement : Statement { toString{ return "exit"; } @@ -454,6 +456,18 @@ class IfStatement : Statement { SplitFlowVisit(v, ifTrue, ifFalse).run_visit(); } } +class BreakStatement : Statement { + toString{ return "break"; } + dbprint { out << "break"; } + visit_children; // in loop-visitor.cpp +} + +class ContinueStatement : Statement { + toString{ return "continue"; } + dbprint { out << "continue"; } + visit_children; // in loop-visitor.cpp +} + class BlockStatement : Statement, ISimpleNamespace, IAnnotated { optional Annotations annotations = Annotations::empty; optional inline IndexedVector components; @@ -464,6 +478,8 @@ class BlockStatement : Statement, ISimpleNamespace, IAnnotated { void push_back(StatOrDecl st) { components.push_back(st); } Annotations getAnnotations() const override { return annotations; } bool empty() const { return components.empty(); } + void append(StatOrDecl stmt); + BlockStatement(std::initializer_list il) { for (auto el : il) append(el); } } class MethodCallStatement : Statement { @@ -500,6 +516,53 @@ class SwitchStatement : Statement { split.run_visit(); } } +/* abstract base class for all loops */ +abstract LoopStatement : Statement, ISimpleNamespace, IAnnotated { + optional Annotations annotations = Annotations::empty; + Annotations getAnnotations() const override { return annotations; } +} + +class ForStatement : LoopStatement { + inline IndexedVector init; + Expression condition; + inline IndexedVector updates; + Statement body; + IDeclaration getDeclByName(cstring name) const override { + return init.getDeclaration(name); } + Util::Enumerator* getDeclarations() const override { + return init.getDeclarations(); } + visit_children; +#emit + // template single implementation of const vs non-const ForStatement + template static void visit_children(THIS *, Visitor &v); +#end +} + +// FIXME -- should we try to directly convert this to a ForStatement in the parser? +class ForInStatement : LoopStatement { + NullOK Declaration_Variable decl; + // the declaration will be moved to the enclosing block by MoveDeclarations, but + // we keep a ref (PathExpression) to it that will be set by the ctor + PathExpression ref = nullptr; + Expression collection; + Statement body; + ForInStatement { ref = new PathExpression(decl->name); } + ForInStatement(Util::SourceInfo si, Annotations a, PathExpression pe, Expression c, Statement b) + : LoopStatement(si, a), decl(nullptr), ref(pe), collection(c), body(b) {} + IDeclaration getDeclByName(cstring name) const override { + return decl && decl->name == name ? decl : nullptr; } + Util::Enumerator* getDeclarations() const override { + if (decl) return new Util::SingleEnumerator(decl); + return new Util::EmptyEnumerator(); } + visit_children; +#emit + // template single implementation of const vs non-const ForInStatement + template static void visit_children(THIS *, Visitor &v); +#end +} + +///////////////////////////////////////////////////////////// + class Function : Declaration, IFunctional, IAnnotated, ISimpleNamespace, INestedNamespace { optional Annotations annotations = Annotations::empty; Type_Method type; diff --git a/ir/loop-visitor.cpp b/ir/loop-visitor.cpp new file mode 100644 index 0000000000..261f578e02 --- /dev/null +++ b/ir/loop-visitor.cpp @@ -0,0 +1,95 @@ +/* +Copyright 2024 NVIDIA CORPORATION. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#include "ir/ir.h" + +template +void IR::ForStatement::visit_children(THIS *self, Visitor &v) { + v.visit(self->annotations, "annotations"); + v.visit(self->init, "init"); + if (auto *cfv = v.controlFlowVisitor()) { + ControlFlowVisitor::SaveGlobal outer(*cfv, "-BREAK-", "-CONTINUE-"); + ControlFlowVisitor *top = nullptr; + while (true) { + top = &cfv->flow_clone(); + cfv->visit(self->condition, "condition", 1000); + auto &inloop = cfv->flow_clone(); + inloop.visit(self->body, "body"); + inloop.flow_merge_global_from("-CONTINUE-"); + inloop.visit(self->updates, "updates"); + inloop.flow_merge(*top); + if (inloop == *top) break; + cfv->flow_copy(inloop); + } + cfv->flow_merge_global_from("-BREAK-"); + } else { + /* Since there is a variable number of init statements (0 or more), we + * don't know what the child index of subsequent children will be. So we + * arbitrarily set the child index of "condition" to 1000. As long as there + * are fewer than 1000 initializers, they'll be child_index 0-999, condition + * will be 1000, body will be 1001, and updates will be 1002+. This is + * only relevant for passes that want to know which child is currently + * being visited from the Visitor::Context */ + v.visit(self->condition, "condition", 1000); + v.visit(self->body, "body"); + v.visit(self->updates, "updates"); + } +} + +void IR::ForStatement::visit_children(Visitor &v) { visit_children(this, v); } +void IR::ForStatement::visit_children(Visitor &v) const { visit_children(this, v); } + +template +void IR::ForInStatement::visit_children(THIS *self, Visitor &v) { + v.visit(self->annotations, "annotations"); + v.visit(self->decl, "decl", 0); + v.visit(self->collection, "collection", 2); + if (auto *cfv = v.controlFlowVisitor()) { + ControlFlowVisitor::SaveGlobal outer(*cfv, "-BREAK-", "-CONTINUE-"); + ControlFlowVisitor *top = nullptr; + do { + top = &cfv->flow_clone(); + cfv->visit(self->ref, "ref", 1); + cfv->visit(self->body, "body", 3); + cfv->flow_merge_global_from("-CONTINUE-"); + } while (*cfv != *top); + cfv->flow_merge_global_from("-BREAK-"); + } else { + v.visit(self->ref, "ref", 1); + v.visit(self->body, "body", 3); + } +} +void IR::ForInStatement::visit_children(Visitor &v) { visit_children(this, v); } +void IR::ForInStatement::visit_children(Visitor &v) const { visit_children(this, v); } + +void IR::BreakStatement::visit_children(Visitor &v) const { + if (auto *cfv = v.controlFlowVisitor()) { + cfv->flow_merge_global_to("-BREAK-"); + cfv->setUnreachable(); + } +} +void IR::BreakStatement::visit_children(Visitor &v) { + return const_cast(this)->visit_children(v); +} + +void IR::ContinueStatement::visit_children(Visitor &v) const { + if (auto *cfv = v.controlFlowVisitor()) { + cfv->flow_merge_global_to("-CONTINUE-"); + cfv->setUnreachable(); + } +} +void IR::ContinueStatement::visit_children(Visitor &v) { + return const_cast(this)->visit_children(v); +} diff --git a/ir/node.h b/ir/node.h index ef9fcf0040..5c51bfebf9 100644 --- a/ir/node.h +++ b/ir/node.h @@ -108,8 +108,6 @@ class Node : public virtual INode { protected: static int currentId; void traceVisit(const char *visitor) const; - virtual void visit_children(Visitor &) {} - virtual void visit_children(Visitor &) const {} friend class ::Visitor; friend class ::Inspector; friend class ::Modifier; @@ -158,6 +156,8 @@ class Node : public virtual INode { virtual bool operator==(const CLASS &) const { return false; } IRNODE_ALL_SUBCLASSES(DEFINE_OPEQ_FUNC) #undef DEFINE_OPEQ_FUNC + virtual void visit_children(Visitor &) {} + virtual void visit_children(Visitor &) const {} bool operator!=(const Node &n) const { return !operator==(n); } diff --git a/ir/pattern.h b/ir/pattern.h index 1b034961c3..0972489225 100644 --- a/ir/pattern.h +++ b/ir/pattern.h @@ -102,6 +102,7 @@ class Pattern { Pattern operator<=(const Pattern &a) { return Pattern(*this) <= a; } Pattern operator>(const Pattern &a) { return Pattern(*this) > a; } Pattern operator>=(const Pattern &a) { return Pattern(*this) >= a; } + Pattern Relation(const Pattern &a) { return Pattern(*this).Relation(a); } Pattern operator&(const Pattern &a) { return Pattern(*this) & a; } Pattern operator|(const Pattern &a) { return Pattern(*this) | a; } Pattern operator^(const Pattern &a) { return Pattern(*this) ^ a; } @@ -162,6 +163,9 @@ class Pattern { Pattern operator>=(const Pattern &r) const { return Pattern(new Binary(pattern, r.pattern)); } + Pattern Relation(const Pattern &r) const { + return Pattern(new Binary(pattern, r.pattern, true)); + } Pattern operator&(const Pattern &r) const { return Pattern(new Binary(pattern, r.pattern, true)); } diff --git a/ir/visitor.cpp b/ir/visitor.cpp index f2b2299f87..c4af4c42eb 100644 --- a/ir/visitor.cpp +++ b/ir/visitor.cpp @@ -56,11 +56,13 @@ class Visitor::ChangeTracker { const IR::Node *result; }; using visited_t = absl::flat_hash_map; + bool forceClone; visited_t visited; public: - ChangeTracker() - : visited(16) {} // Pre-allocate 16 slots as usually these maps are small, but we do create + explicit ChangeTracker(bool forceClone) + : forceClone(forceClone), + visited(16) {} // Pre-allocate 16 slots as usually these maps are small, but we do create // lots of them. This saves quite some time for rehashes /** Begin tracking @n during a visiting pass. Use `finish(@n)` to mark @n as @@ -107,7 +109,7 @@ class Visitor::ChangeTracker { if (!final) { orig_visit_info->result = final; return true; - } else if (final != orig && *final != *orig) { + } else if (forceClone || (final != orig && *final != *orig)) { orig_visit_info->result = final; visited.emplace(final, visit_info_t{false, orig_visit_info->visitOnce, final}); return true; @@ -351,7 +353,7 @@ Visitor::profile_t Visitor::init_apply(const IR::Node *root, const Context *pare } Visitor::profile_t Modifier::init_apply(const IR::Node *root) { auto rv = Visitor::init_apply(root); - visited = std::make_shared(); + visited = std::make_shared(forceClone); return rv; } Visitor::profile_t Inspector::init_apply(const IR::Node *root) { @@ -361,7 +363,7 @@ Visitor::profile_t Inspector::init_apply(const IR::Node *root) { } Visitor::profile_t Transform::init_apply(const IR::Node *root) { auto rv = Visitor::init_apply(root); - visited = std::make_shared(); + visited = std::make_shared(forceClone); return rv; } void Visitor::end_apply() {} @@ -471,7 +473,7 @@ class ForwardChildren : public Visitor { } // namespace const IR::Node *Modifier::apply_visitor(const IR::Node *n, const char *name) { - if (ctxt) ctxt->child_name = name; + if (ctxt && name) ctxt->child_name = name; if (n) { PushContext local(ctxt, n); switch (visited->try_start(n, visitDagOnce)) { @@ -508,7 +510,7 @@ const IR::Node *Modifier::apply_visitor(const IR::Node *n, const char *name) { } const IR::Node *Inspector::apply_visitor(const IR::Node *n, const char *name) { - if (ctxt) ctxt->child_name = name; + if (ctxt && name) ctxt->child_name = name; if (n && !join_flows(n)) { PushContext local(ctxt, n); switch (visited->try_start(n, visitDagOnce)) { @@ -536,7 +538,7 @@ const IR::Node *Inspector::apply_visitor(const IR::Node *n, const char *name) { } const IR::Node *Transform::apply_visitor(const IR::Node *n, const char *name) { - if (ctxt) ctxt->child_name = name; + if (ctxt && name) ctxt->child_name = name; if (n) { PushContext local(ctxt, n); switch (visited->try_start(n, visitDagOnce)) { diff --git a/ir/visitor.h b/ir/visitor.h index f407c1e169..9a70189573 100644 --- a/ir/visitor.h +++ b/ir/visitor.h @@ -65,8 +65,8 @@ struct Visitor_Context { } }; +class ControlFlowVisitor; class SplitFlowVisit_base; - class Inspector; class Visitor { @@ -197,6 +197,7 @@ class Visitor { virtual bool check_clone(const Visitor *a) { return typeid(*this) == typeid(*a); } // Functions for IR visit_children to call for ControlFlowVisitors. + virtual ControlFlowVisitor *controlFlowVisitor() { return nullptr; } virtual Visitor &flow_clone() { return *this; } // all flow_clones share a split_link chain to allow stack walking SplitFlowVisit_base *split_link_mem = nullptr, *&split_link; @@ -206,6 +207,7 @@ class Visitor { * control flow graph. Should update @this and leave the other unchanged. */ virtual void flow_merge(Visitor &) {} + virtual bool flow_merge_closure(Visitor &) { BUG("%s pass does not support loops", name()); } /** Support methods for non-local ControlFlow computations */ virtual void flow_merge_global_to(cstring) {} virtual void flow_merge_global_from(cstring) {} @@ -391,6 +393,9 @@ class Modifier : public virtual Visitor { bool visit_in_progress(const IR::Node *) const; void visitOnce() const override; void visitAgain() const override; + + protected: + bool forceClone = false; // force clone whole tree even if unchanged }; class Inspector : public virtual Visitor { @@ -450,6 +455,7 @@ class Transform : public virtual Visitor { prune_flag = true; return rv; } + bool forceClone = false; // force clone whole tree even if unchanged }; // turn this on for extra info tracking control joinFlows for debugging @@ -479,6 +485,11 @@ class ControlFlowVisitor : public virtual Visitor { friend void dump(const flow_join_points_t &); friend void dump(const flow_join_points_t *); + // Flag set by visit_children of nodes that are unconditional branches, to denote that + // the control flow is currently unreachable. Future flow_merges to this visitor should + // clear this if merging a reachable state. + bool unreachable = false; + flow_join_points_t *flow_join_points = 0; class SetupJoinPoints : public Inspector { protected: @@ -518,12 +529,19 @@ class ControlFlowVisitor : public virtual Visitor { * edge are never join points. */ virtual bool filter_join_point(const IR::Node *) { return false; } - ControlFlowVisitor &flow_clone() override; - void flow_merge(Visitor &) override = 0; - virtual void flow_copy(ControlFlowVisitor &) = 0; ControlFlowVisitor() : globals(*new std::map) {} public: + ControlFlowVisitor *controlFlowVisitor() override { return this; } + ControlFlowVisitor &flow_clone() override; + void flow_merge(Visitor &) override = 0; + virtual void flow_copy(ControlFlowVisitor &) = 0; + virtual bool operator==(const ControlFlowVisitor &) const { + BUG("%s pass does not support loops", name()); + } + bool operator!=(const ControlFlowVisitor &v) const { return !(*this == v); } + void setUnreachable() { unreachable = true; } + bool isUnreachable() { return unreachable; } void flow_merge_global_to(cstring key) override { if (globals.count(key)) globals.at(key).flow_merge(*this); @@ -536,6 +554,18 @@ class ControlFlowVisitor : public virtual Visitor { void erase_global(cstring key) override { globals.erase(key); } bool check_global(cstring key) override { return globals.count(key) != 0; } void clear_globals() override { globals.clear(); } + std::pair save_global(cstring key) { + ControlFlowVisitor *cfv = nullptr; + if (auto i = globals.find(key); i != globals.end()) { + cfv = &i->second; + globals.erase(i); + } + return std::make_pair(key, cfv); + } + void restore_global(std::pair saved) { + globals.erase(saved.first); + if (saved.second) globals.emplace(saved.first, *saved.second); + } /// RAII class to ensure global key is only used in one place class GuardGlobal { @@ -548,6 +578,23 @@ class ControlFlowVisitor : public virtual Visitor { } ~GuardGlobal() { self.erase_global(key); } }; + /// RAII class to save and restore one or more global keys + class SaveGlobal { + ControlFlowVisitor &self; + std::vector> saved; + + public: + SaveGlobal(ControlFlowVisitor &self, cstring key) : self(self) { + saved.push_back(self.save_global(key)); + } + SaveGlobal(ControlFlowVisitor &self, cstring k1, cstring k2) : self(self) { + saved.push_back(self.save_global(k1)); + saved.push_back(self.save_global(k2)); + } + ~SaveGlobal() { + for (auto it = saved.rbegin(); it != saved.rend(); ++it) self.restore_global(*it); + } + }; bool has_flow_joins() const override { return !!flow_join_points; } const flow_join_info_t *flow_join_status(const IR::Node *n) const { diff --git a/ir/write_context.cpp b/ir/write_context.cpp index 676efc262c..6b023acc53 100644 --- a/ir/write_context.cpp +++ b/ir/write_context.cpp @@ -54,6 +54,8 @@ bool P4WriteContext::isWrite(bool root_value) { return true; } } + // The `ref` of a for..in is written and read + if (ctxt->node->is()) return ctxt->child_index == 1; if (ctxt->node->is()) { /* receiver of a method call -- some methods might be 'const' and not modify * their receiver, but we currently have no way of determining that */ diff --git a/lib/enumerator.h b/lib/enumerator.h index fe9c2eda82..5ae1f5ccab 100644 --- a/lib/enumerator.h +++ b/lib/enumerator.h @@ -256,6 +256,40 @@ class IteratorEnumerator : public Enumerator { ///////////////////////////////////////////////////////////////////// +template +class SingleEnumerator : public Enumerator { + T value; + + public: + explicit SingleEnumerator(T v) : Enumerator(), value(v) {} + bool moveNext() { + switch (this->state) { + case EnumeratorState::NotStarted: + this->state = EnumeratorState::Valid; + return true; + case EnumeratorState::PastEnd: + return false; + case EnumeratorState::Valid: + this->state = EnumeratorState::PastEnd; + return false; + } + throw std::runtime_error("Unexpected enumerator state"); + } + T getCurrent() const { + switch (this->state) { + case EnumeratorState::NotStarted: + throw std::logic_error("You cannot call 'getCurrent' before 'moveNext'"); + case EnumeratorState::PastEnd: + throw std::logic_error("You cannot call 'getCurrent' past the collection end"); + case EnumeratorState::Valid: + return this->value; + } + throw std::runtime_error("Unexpected enumerator state"); + } +}; + +///////////////////////////////////////////////////////////////////// + /// Always empty iterator (equivalent to end()) template class EmptyEnumerator : public Enumerator { diff --git a/lib/sourceCodeBuilder.h b/lib/sourceCodeBuilder.h index ff0ebbbebc..f5c9545d7c 100644 --- a/lib/sourceCodeBuilder.h +++ b/lib/sourceCodeBuilder.h @@ -33,6 +33,7 @@ class SourceCodeBuilder { std::stringstream buffer; const std::string nl = "\n"; bool endsInSpace; + bool supressSemi = false; public: SourceCodeBuilder() : indentLevel(0), indentAmount(4), endsInSpace(false) {} @@ -82,9 +83,11 @@ class SourceCodeBuilder { void append(int u) { appendFormat("%d", u); } void endOfStatement(bool addNl = false) { - append(";"); + if (!supressSemi) append(";"); + supressSemi = false; if (addNl) newline(); } + void supressStatementSemi() { supressSemi = true; } void blockStart() { append("{"); diff --git a/lib/source_file.cpp b/lib/source_file.cpp index e0a34151db..65bd2aac37 100644 --- a/lib/source_file.cpp +++ b/lib/source_file.cpp @@ -317,4 +317,5 @@ cstring SourceFileLine::toString() const { [[gnu::used]] // ensure linker will not drop function even if unused void dbprint(const IHasDbPrint *o) { o->dbprint(std::cout); + std::cout << std::endl << std::flush; } diff --git a/midend/CMakeLists.txt b/midend/CMakeLists.txt index 2be73da2f3..f2716798fb 100644 --- a/midend/CMakeLists.txt +++ b/midend/CMakeLists.txt @@ -58,6 +58,7 @@ set (MIDEND_SRCS simplifySelectList.cpp singleArgumentSelect.cpp tableHit.cpp + unrollLoops.cpp validateProperties.cpp ) @@ -111,6 +112,7 @@ set (MIDEND_HDRS simplifySelectList.h singleArgumentSelect.h tableHit.h + unrollLoops.h validateProperties.h ) diff --git a/midend/actionSynthesis.cpp b/midend/actionSynthesis.cpp index 502f57618e..502c40f995 100644 --- a/midend/actionSynthesis.cpp +++ b/midend/actionSynthesis.cpp @@ -205,11 +205,21 @@ const IR::Statement *DoSynthesizeActions::createAction(const IR::Statement *toAd } const IR::Node *DoSynthesizeActions::preorder(IR::AssignmentStatement *statement) { + // don't move stuff from for init/update -- should be part of policy? + auto *ctxt = getContext(); + if (ctxt->node->is() && + (ctxt->child_name[0] == 'i' || ctxt->child_name[0] == 'u')) + return statement; if (mustMove(statement)) return createAction(statement); return statement; } const IR::Node *DoSynthesizeActions::preorder(IR::MethodCallStatement *statement) { + // don't move stuff from for init/update -- should be part of policy? + auto *ctxt = getContext(); + if (ctxt->node->is() && + (ctxt->child_name[0] == 'i' || ctxt->child_name[0] == 'u')) + return statement; if (mustMove(statement)) return createAction(statement); return statement; } diff --git a/midend/def_use.cpp b/midend/def_use.cpp index 375c9f889f..ac16129c7d 100644 --- a/midend/def_use.cpp +++ b/midend/def_use.cpp @@ -24,13 +24,26 @@ const ordered_set ComputeDefUse::empty = {}; void ComputeDefUse::flow_merge(Visitor &a_) { ComputeDefUse &a = dynamic_cast(a_); + unreachable &= a.unreachable; for (auto &di : a.def_info) def_info[di.first].flow_merge(di.second); } void ComputeDefUse::flow_copy(ControlFlowVisitor &a_) { ComputeDefUse &a = dynamic_cast(a_); BUG_CHECK(state == a.state, "inconsistent state in ComputeDefUse::flow_copy"); + unreachable = a.unreachable; def_info = a.def_info; } +bool ComputeDefUse::operator==(const ControlFlowVisitor &a_) const { + auto &a = dynamic_cast(a_); + BUG_CHECK(state == a.state, "inconsistent state in ComputeDefUse::=="); + if (unreachable != a.unreachable) return false; + if (def_info.size() != a.def_info.size()) return false; + for (auto &[decl, di] : def_info) { + if (!a.def_info.count(decl)) return false; + if (di != a.def_info.at(decl)) return false; + } + return true; +} ComputeDefUse::def_info_t::def_info_t(const def_info_t &a) : defs(a.defs), @@ -70,6 +83,31 @@ void ComputeDefUse::def_info_t::flow_merge(def_info_t &a) { slices_sanity(); } +bool ComputeDefUse::def_info_t::operator==(const def_info_t &a) const { + if (defs.size() != a.defs.size()) return false; + for (auto *l : defs) + if (!a.defs.count(l)) return false; + if (live != a.live) return false; + // Don't check the parent field as it is not set consistently (it is only set in + // copy/move ctors above) and nothing appears to depend on it. Should be removed? + if (valid_bit_defs.size() != a.valid_bit_defs.size()) return false; + for (auto *l : valid_bit_defs) + if (!a.valid_bit_defs.count(l)) return false; + if (fields.size() != a.fields.size()) return false; + for (auto &[field, info] : fields) { + auto it = a.fields.find(field); + if (it == a.fields.end()) return false; + if (info != it->second) return false; + } + if (slices.size() != a.slices.size()) return false; + for (auto &[slice, info] : slices) { + auto it = a.slices.find(slice); + if (it == a.slices.end()) return false; + if (info != it->second) return false; + } + return true; +} + class ComputeDefUse::SetupJoinPoints : public ControlFlowVisitor::SetupJoinPoints, public P4::ResolutionContext { bool preorder(const IR::ParserState *n) override { diff --git a/midend/def_use.h b/midend/def_use.h index 564df7c0b9..e583b06e9c 100644 --- a/midend/def_use.h +++ b/midend/def_use.h @@ -46,6 +46,8 @@ class ComputeDefUse : public Inspector, ComputeDefUse *clone() const override { return new ComputeDefUse(*this); } void flow_merge(Visitor &) override; void flow_copy(ControlFlowVisitor &) override; + bool operator==(const ControlFlowVisitor &) const override; + enum { SKIPPING, NORMAL, READ_ONLY, WRITE_ONLY } state = SKIPPING; public: @@ -83,6 +85,8 @@ class ComputeDefUse : public Inspector, // for those bits/elements/fields where live is set. ordered_set defs; bitvec live; + // FIXME -- this parent field is never used and is not set consistently, so + // appears to be useless? def_info_t *parent = nullptr; // track valid bit access for headers separate from the rest of the header ordered_set valid_bit_defs; @@ -95,6 +99,8 @@ class ComputeDefUse : public Inspector, void erase_slice(le_bitrange); void split_slice(le_bitrange); void flow_merge(def_info_t &); + bool operator==(const def_info_t &) const; + bool operator!=(const def_info_t &a) const { return !(*this == a); } def_info_t() = default; def_info_t(const def_info_t &); def_info_t(def_info_t &&); @@ -115,6 +121,7 @@ class ComputeDefUse : public Inspector, profile_t init_apply(const IR::Node *root) override { auto rv = Inspector::init_apply(root); + LOG3("## Midend ComputeDefUse"); state = SKIPPING; clear(); return rv; @@ -145,6 +152,7 @@ class ComputeDefUse : public Inspector, ComputeDefUse() : ResolutionContext(true), cached_locs(*new std::set), defuse(*new defuse_t) { joinFlows = true; + visitDagOnce = false; } void clear() { cached_locs.clear(); diff --git a/midend/global_copyprop.cpp b/midend/global_copyprop.cpp index ee664cd8a0..2d816f17ef 100644 --- a/midend/global_copyprop.cpp +++ b/midend/global_copyprop.cpp @@ -122,6 +122,28 @@ bool FindVariableValues::preorder(const IR::SwitchStatement *stat) { return false; } +// Loops are treated like ifs, as the body may run multiple times or may not run +bool FindVariableValues::preorder(const IR::ForStatement *stat) { + visit(stat->init, "init"); + std::map copyOfVars(vars); + visit(stat->condition, "condition"); + visit(stat->body, "body"); + compareValuesInMaps(©OfVars, &vars); + vars = copyOfVars; + visit(stat->updates, "updates"); + compareValuesInMaps(©OfVars, &vars); + vars = copyOfVars; + return false; +} +bool FindVariableValues::preorder(const IR::ForInStatement *stat) { + std::map copyOfVars(vars); + removeVarsContaining(&vars, stat->ref->path->name); + visit(stat->body, "body"); + compareValuesInMaps(©OfVars, &vars); + vars = copyOfVars; + return false; +} + // Update the value for the 'stat->left' variable. bool FindVariableValues::preorder(const IR::AssignmentStatement *stat) { if (!working || GlobalCopyProp::lValueName(stat->left).isNullOrEmpty()) return false; @@ -280,6 +302,62 @@ IR::IfStatement *DoGlobalCopyPropagation::preorder(IR::IfStatement *stat) { return stat; } +/** remove all the vars that might be modified by the code visited from the `vars` map + */ +class RemoveModifiedValues : public Inspector { + ReferenceMap *refMap; + TypeMap *typeMap; + std::map *vars; + + bool preorder(const IR::AssignmentStatement *stat) override { + if ((*vars)[GlobalCopyProp::lValueName(stat->left)] == nullptr || + !(stat->right->equiv(*((*vars)[GlobalCopyProp::lValueName(stat->left)])))) + removeVarsContaining(vars, GlobalCopyProp::lValueName(stat->left)); + return true; + } + bool preorder(const IR::MethodCallExpression *mc) override { + auto *mi = MethodInstance::resolve(mc, refMap, typeMap, true); + if (auto eFun = mi->to()) { + LOG6(" Is 'ExternFunction'. Checking params for: " << eFun->method); + checkParametersForMap(eFun->method->getParameters(), vars); + } else if (auto fCall = mi->to()) { + LOG6(" Is 'FunctionCall'. Checking params for: " << fCall->function); + checkParametersForMap(fCall->function->getParameters(), vars); + } + return true; + } + + public: + RemoveModifiedValues(ReferenceMap *rM, TypeMap *tM, + std::map *v) + : refMap(rM), typeMap(tM), vars(v) {} +}; + +IR::ForStatement *DoGlobalCopyPropagation::preorder(IR::ForStatement *stat) { + if (!performRewrite) return stat; + visit(stat->init, "init"); + stat->body->apply(RemoveModifiedValues(refMap, typeMap, vars)); + stat->updates.apply(RemoveModifiedValues(refMap, typeMap, vars)); + visit(stat->condition, "condition"); + visit(stat->body, "body"); + visit(stat->updates, "updates"); + stat->body->apply(RemoveModifiedValues(refMap, typeMap, vars)); + stat->updates.apply(RemoveModifiedValues(refMap, typeMap, vars)); + prune(); + return stat; +} + +IR::ForInStatement *DoGlobalCopyPropagation::preorder(IR::ForInStatement *stat) { + if (!performRewrite) return stat; + visit(stat->collection, "collection"); + removeVarsContaining(vars, stat->ref->path->name); + stat->body->apply(RemoveModifiedValues(refMap, typeMap, vars)); + visit(stat->body, "body"); + stat->body->apply(RemoveModifiedValues(refMap, typeMap, vars)); + prune(); + return stat; +} + // Propagate values for variables on the right side of the statement // and update value for 'stat->left' variable if needed. const IR::Node *DoGlobalCopyPropagation::preorder(IR::AssignmentStatement *stat) { diff --git a/midend/global_copyprop.h b/midend/global_copyprop.h index ac38932a13..7b80edf259 100644 --- a/midend/global_copyprop.h +++ b/midend/global_copyprop.h @@ -78,6 +78,8 @@ class FindVariableValues final : public Inspector { bool preorder(const IR::IfStatement *) override; bool preorder(const IR::SwitchStatement *) override; + bool preorder(const IR::ForStatement *) override; + bool preorder(const IR::ForInStatement *) override; void postorder(const IR::P4Control *) override; bool preorder(const IR::P4Control *) override; bool preorder(const IR::P4Table *) override; @@ -126,6 +128,8 @@ class DoGlobalCopyPropagation final : public Transform { const IR::Expression *copyprop_name(cstring name); IR::IfStatement *preorder(IR::IfStatement *) override; + IR::ForStatement *preorder(IR::ForStatement *) override; + IR::ForInStatement *preorder(IR::ForInStatement *) override; const IR::Expression *postorder(IR::PathExpression *) override; const IR::Expression *preorder(IR::ArrayIndex *) override; const IR::Expression *preorder(IR::Member *) override; diff --git a/midend/local_copyprop.cpp b/midend/local_copyprop.cpp index 490553cd4a..9bbe021d67 100644 --- a/midend/local_copyprop.cpp +++ b/midend/local_copyprop.cpp @@ -56,6 +56,8 @@ static cstring expr_name(const IR::Expression *exp) { return cstring(); } +int DoLocalCopyPropagation::uid_ctr = 0; + /* LocalCopyPropagation does copy propagation and dead code elimination within a 'block' * the body of an action or control (TODO -- extend to parsers/states). Within the * block it tracks all variables defined in the block as well as those defined outside the @@ -177,11 +179,21 @@ class DoLocalCopyPropagation::RewriteTableKeys : public Transform { void DoLocalCopyPropagation::flow_merge(Visitor &a_) { auto &a = dynamic_cast(a_); BUG_CHECK(working == a.working, "inconsitent DoLocalCopyPropagation state on merge"); + LOG8("flow_merge " << a.uid << " into " << uid); + unreachable &= a.unreachable; for (auto &var : available) { if (auto merge = ::getref(a.available, var.first)) { - if (merge->val != var.second.val) var.second.val = nullptr; + if (merge->val != var.second.val) { + if (var.second.val) { + LOG4(" dropping " << var.first << " = " << var.second.val + << " in flow_merge"); + } + var.second.val = nullptr; + } if (merge->live) var.second.live = true; } else { + if (var.second.val) + LOG4(" dropping " << var.first << " = " << var.second.val << " in flow_merge"); var.second.val = nullptr; } } @@ -190,12 +202,31 @@ void DoLocalCopyPropagation::flow_merge(Visitor &a_) { void DoLocalCopyPropagation::flow_copy(ControlFlowVisitor &a_) { auto &a = dynamic_cast(a_); BUG_CHECK(working == a.working, "inconsistent DoLocalCopyPropagation state on copy"); + LOG8("flow_copy " << a.uid << " into " << uid); + unreachable = a.unreachable; available = a.available; need_key_rewrite = a.need_key_rewrite; BUG_CHECK(inferForTable == a.inferForTable, "inconsistent DoLocalCopyPropagation state on copy"); BUG_CHECK(inferForFunc == a.inferForFunc, "inconsistent DoLocalCopyPropagation state on copy"); } +bool DoLocalCopyPropagation::operator==(const ControlFlowVisitor &a_) const { + auto &a = dynamic_cast(a_); + BUG_CHECK(working == a.working, "inconsistent DoLocalCopyPropagation state on =="); + if (unreachable != a.unreachable) return false; + auto it = a.available.begin(); + for (auto &var : available) { + if (it == a.available.end()) return false; + if (var.first != it->first) return false; + if (var.second.local != it->second.local) return false; + if (var.second.live != it->second.live) return false; + if (var.second.val != it->second.val) return false; + ++it; + } + if (it != a.available.end()) return false; + if (need_key_rewrite != a.need_key_rewrite) return false; + return true; +} /// test to see if names denote overlapping locations bool DoLocalCopyPropagation::name_overlap(cstring name1, cstring name2) { @@ -405,6 +436,10 @@ IR::AssignmentStatement *DoLocalCopyPropagation::postorder(IR::AssignmentStateme return as; } +void DoLocalCopyPropagation::LoopPrepass::postorder(const IR::AssignmentStatement *as) { + if (auto dest = expr_name(as->left)) self.dropValuesUsing(dest); +} + IR::IfStatement *DoLocalCopyPropagation::postorder(IR::IfStatement *s) { if (s->ifTrue == nullptr) { /* can't leave ifTrue == nullptr, as that will fail validation -- fold away @@ -425,6 +460,32 @@ IR::IfStatement *DoLocalCopyPropagation::postorder(IR::IfStatement *s) { return s; } +IR::ForStatement *DoLocalCopyPropagation::preorder(IR::ForStatement *s) { + visit(s->init, "init"); + s->apply(LoopPrepass(*this), getContext()); + ControlFlowVisitor::SaveGlobal outer(*this, "-BREAK-", "-CONTINUE-"); + visit(s->condition, "condition"); + visit(s->body, "body"); + flow_merge_global_from("-CONTINUE-"); + visit(s->updates, "updates"); + flow_merge_global_from("-BREAK-"); + prune(); + return s; +} + +IR::ForInStatement *DoLocalCopyPropagation::preorder(IR::ForInStatement *s) { + visit(s->decl, "decl", 0); + visit(s->collection, "collection", 2); + s->apply(LoopPrepass(*this), getContext()); + ControlFlowVisitor::SaveGlobal outer(*this, "-BREAK-", "-CONTINUE-"); + visit(s->ref, "ref", 1); + visit(s->body, "body", 3); + flow_merge_global_from("-CONTINUE-"); + flow_merge_global_from("-BREAK-"); + prune(); + return s; +} + bool isAsync(const IR::Vector methods, cstring callee, cstring caller) { if (callee[0] == '.') callee = callee.substr(1); for (auto *m : methods) { @@ -533,6 +594,77 @@ IR::MethodCallExpression *DoLocalCopyPropagation::postorder(IR::MethodCallExpres return mc; } +// FIXME -- this duplicates much of what is in the above method -- factor things better +void DoLocalCopyPropagation::LoopPrepass::postorder(const IR::MethodCallExpression *mc) { + auto *mi = MethodInstance::resolve(mc, self.refMap, self.typeMap, true); + if (auto mem = mc->method->to()) { + if (auto obj = expr_name(mem->expr)) { + if (self.tables.count(obj)) { + LOG3("loop prepass table apply method call " << mc->method); + apply_table(&self.tables[obj]); + return; + } else if (auto em = mi->to()) { + auto ext = em->actualExternType; + auto name = obj + '.' + mem->member; + if (self.methods.count(name)) { + LOG3("loop prepass concrete method call " << name); + apply_function(&self.methods[name]); + return; + } else if (ext && (ext->name == "packet_in" || ext->name == "packet_out")) { + LOG3("loop prepass " << ext->name << '.' << mem->member << " call"); + // we currently do no track the liveness of packet_in/out objects + return; + } else { + // extern method call might trigger various concrete implementation + // method in the object, so act as if all of them are applied + // FIXME -- Could it invoke methods on other objects or otherwise affect + // global values? Not clear -- we probably need a hook for backends + // to provide per-extern flow info to this (and other) frontend passes. + LOG3("loop prepass extern method call " << name); + for (auto *n : em->mayCall()) { + if (auto *method = ::getref(self.methods, obj + '.' + n->getName())) { + LOG4(" might call " << obj << '.' << n->getName()); + apply_function(method); + } + } + return; + } + } else if (mem->expr->type->is() || + mem->expr->type->is()) { + BUG_CHECK(mem->member == "setValid" || mem->member == "setInvalid", + "Unexpected header method %s", mem->member); + LOG3("loop prepass header method call " << mc->method << " writes to " << obj); + self.dropValuesUsing(obj); + return; + } else if (mem->expr->type->is()) { + BUG_CHECK(mem->member == "push_front" || mem->member == "pop_front", + "Unexpected stack method %s", mem->member); + self.dropValuesUsing(obj); + return; + } + } + } else if (auto fn = mc->method->to()) { + if (self.actions.count(fn->path->name)) { + LOG3("loop prepass action method call " << mc->method); + apply_function(&self.actions[fn->path->name]); + return; + } else if (mi->is()) { + LOG3("self.extern function call " << mc->method); + // assume it has no side-effects on anything not explicitly passed to it? + // maybe should have annotations if it does + return; + } + } + LOG3("loop prepass unknown method call " << mc->method << " clears all nonlocal saved values"); + for (auto &var : self.available) { + if (!var.second.local) { + LOG7(" may access non-local " << var.first); + var.second.val = nullptr; + } + } + return; +} + IR::P4Action *DoLocalCopyPropagation::preorder(IR::P4Action *act) { visitOnce(); BUG_CHECK(!working && !inferForFunc && available.empty(), "corrupt internal data struct"); @@ -649,6 +781,11 @@ void DoLocalCopyPropagation::apply_function(DoLocalCopyPropagation::FuncInfo *ac } } +void DoLocalCopyPropagation::LoopPrepass::apply_function(DoLocalCopyPropagation::FuncInfo *act) { + LOG7("loop prepass apply_function writes=" << act->writes); + for (auto write : act->writes) self.dropValuesUsing(write); +} + void DoLocalCopyPropagation::apply_table(DoLocalCopyPropagation::TableInfo *tbl) { ++tbl->apply_count; std::unordered_set remaps_seen; @@ -716,6 +853,10 @@ void DoLocalCopyPropagation::apply_table(DoLocalCopyPropagation::TableInfo *tbl) for (auto action : tbl->actions) apply_function(&actions[action]); } +void DoLocalCopyPropagation::LoopPrepass::apply_table(DoLocalCopyPropagation::TableInfo *tbl) { + for (auto action : tbl->actions) apply_function(&self.actions[action]); +} + IR::P4Table *DoLocalCopyPropagation::preorder(IR::P4Table *tbl) { visitOnce(); BUG_CHECK(!inferForTable, "corrupt internal data struct"); @@ -772,6 +913,9 @@ IR::ParserState *DoLocalCopyPropagation::postorder(IR::ParserState *state) { // Reset the state of internal data structures after traversing IR, // needed for this pass to function correctly when used in a PassRepeated Visitor::profile_t DoLocalCopyPropagation::init_apply(const IR::Node *node) { + auto rv = Transform::init_apply(node); + uid = uid_ctr = 0; // reset uids + // clear maps available.clear(); tables.clear(); @@ -786,7 +930,7 @@ Visitor::profile_t DoLocalCopyPropagation::init_apply(const IR::Node *node) { elimUnusedTables = false; working = false; - return Transform::init_apply(node); + return rv; } } // namespace P4 diff --git a/midend/local_copyprop.h b/midend/local_copyprop.h index 6a335a518a..68ac551a79 100644 --- a/midend/local_copyprop.h +++ b/midend/local_copyprop.h @@ -83,10 +83,18 @@ class DoLocalCopyPropagation : public ControlFlowVisitor, Transform, P4WriteCont bool need_key_rewrite = false; std::function policy; bool elimUnusedTables = false; - - DoLocalCopyPropagation *clone() const override { return new DoLocalCopyPropagation(*this); } + int uid = -1; + static int uid_ctr; + + DoLocalCopyPropagation *clone() const override { + auto *rv = new DoLocalCopyPropagation(*this); + rv->uid = ++uid_ctr; + LOG8("flow_clone(" << uid << ") = " << rv->uid); + return rv; + } void flow_merge(Visitor &) override; void flow_copy(ControlFlowVisitor &) override; + bool operator==(const ControlFlowVisitor &) const override; bool name_overlap(cstring, cstring); void forOverlapAvail(cstring, std::function); void dropValuesUsing(cstring); @@ -95,6 +103,17 @@ class DoLocalCopyPropagation : public ControlFlowVisitor, Transform, P4WriteCont } bool isHeaderUnionIsValid(const IR::Expression *e); + class LoopPrepass : public Inspector { + DoLocalCopyPropagation &self; + void postorder(const IR::AssignmentStatement *) override; + void postorder(const IR::MethodCallExpression *) override; + void apply_table(TableInfo *tbl); + void apply_function(FuncInfo *tbl); + + public: + explicit LoopPrepass(DoLocalCopyPropagation &s) : self(s) {} + }; + void visit_local_decl(const IR::Declaration_Variable *); const IR::Node *postorder(IR::Declaration_Variable *) override; IR::Expression *preorder(IR::Expression *m) override; @@ -106,6 +125,8 @@ class DoLocalCopyPropagation : public ControlFlowVisitor, Transform, P4WriteCont IR::AssignmentStatement *preorder(IR::AssignmentStatement *) override; IR::AssignmentStatement *postorder(IR::AssignmentStatement *) override; IR::IfStatement *postorder(IR::IfStatement *) override; + IR::ForStatement *preorder(IR::ForStatement *) override; + IR::ForInStatement *preorder(IR::ForInStatement *) override; IR::MethodCallExpression *postorder(IR::MethodCallExpression *) override; IR::P4Action *preorder(IR::P4Action *) override; IR::P4Action *postorder(IR::P4Action *) override; diff --git a/midend/removeExits.cpp b/midend/removeExits.cpp index babe5f6bd3..a150d2d21b 100644 --- a/midend/removeExits.cpp +++ b/midend/removeExits.cpp @@ -55,8 +55,11 @@ void DoRemoveExits::callExit(const IR::Node *node) { const IR::Node *DoRemoveExits::preorder(IR::ExitStatement *statement) { set(TernaryBool::Yes); - auto left = new IR::PathExpression(returnVar); - return new IR::AssignmentStatement(statement->srcInfo, left, new IR::BoolLiteral(true)); + auto left = new IR::PathExpression(IR::Type::Boolean::get(), returnVar); + auto trueVal = new IR::BoolLiteral(true); + IR::Statement *rv = new IR::AssignmentStatement(statement->srcInfo, left, trueVal); + if (findContext()) rv = new IR::BlockStatement({rv, new IR::BreakStatement}); + return rv; } const IR::Node *DoRemoveExits::preorder(IR::P4Table *table) { diff --git a/midend/unrollLoops.cpp b/midend/unrollLoops.cpp new file mode 100644 index 0000000000..5dccee8c29 --- /dev/null +++ b/midend/unrollLoops.cpp @@ -0,0 +1,285 @@ +/* +Copyright 2024 Nvidia Corp. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "unrollLoops.h" + +#include "ir/pattern.h" + +/** helper function to create a simple assignment to a boolean flag variable */ +static IR::AssignmentStatement *setFlag(cstring name, bool val) { + auto var = new IR::PathExpression(IR::Type::Boolean::get(), new IR::Path(name)); + return new IR::AssignmentStatement(var, new IR::BoolLiteral(val)); +} + +namespace P4 { + +/** transform to remove break and continue statements from the body of a loop + * This pass is designed to run on just the body of a loop, generally returning a + * new BlockStatement with the break and continue statements removed and replaced + * with new temp bool variables. The declarations and initializations of the temps + * need to be inserted elsewhere -- the temp for continue can be added to the top + * of the loop body (and should be set to false there), but the temp for break needs + * to be defined and set to false outside the loop and should be checked in the loop + * condition + */ +class RemoveBreakContinue : public Transform { + NameGenerator &nameGen; + + public: + explicit RemoveBreakContinue(NameGenerator &ng) : nameGen(ng) {} + + IR::Declaration_Variable *breakFlag = nullptr; + IR::Declaration_Variable *continueFlag = nullptr; + bool needFlagCheck = false; + + private: + profile_t init_apply(const IR::Node *root) override { + breakFlag = continueFlag = nullptr; + needFlagCheck = false; + return Transform::init_apply(root); + } + + // skip nested loops -- they'll need to be expanded themselves + IR::Node *preorder(IR::ForStatement *s) override { + prune(); + return preorder(static_cast(s)); + } + IR::Node *preorder(IR::ForInStatement *s) override { + prune(); + return preorder(static_cast(s)); + } + + IR::Node *postorder(IR::BreakStatement *) override { + if (!breakFlag) { + breakFlag = + new IR::Declaration_Variable(nameGen.newName("breakFlag"), IR::Type_Boolean::get()); + } + needFlagCheck = true; + return setFlag(breakFlag->name, true); + } + IR::Node *postorder(IR::ContinueStatement *) override { + if (!continueFlag) { + continueFlag = new IR::Declaration_Variable(nameGen.newName("continueFlag"), + IR::Type_Boolean::get()); + } + needFlagCheck = true; + return setFlag(continueFlag->name, true); + } + IR::Node *preorder(IR::Statement *s) override { + if (!needFlagCheck) return s; + const IR::Expression *cond = nullptr; + if (breakFlag) cond = new IR::LNot(new IR::PathExpression(breakFlag->name)); + if (continueFlag) { + const IR::Expression *c2 = new IR::LNot(new IR::PathExpression(continueFlag->name)); + cond = cond ? new IR::LAnd(cond, c2) : c2; + } + BUG_CHECK(cond, "need flag check but no flags?"); + needFlagCheck = false; + s->visit_children(*this); + needFlagCheck = true; + prune(); + auto s2 = s->apply_visitor_postorder(*this)->to(); + BUG_CHECK(s2, "RemoveBreakContinue::postorder failed to return a statement"); + return new IR::IfStatement(cond, s2, nullptr); + } +}; + +/* replace references to the 'index' var with a constant */ +class ReplaceIndexRefs : public Transform, P4WriteContext { + cstring indexVar; + long value; + bool stop_after_modification = false; + + IR::Node *preorder(IR::PathExpression *pe) { + if (stop_after_modification || pe->path->name != indexVar) return pe; + if (isWrite()) { + stop_after_modification = true; + return pe; + } + return new IR::Constant(pe->type, value); + } + IR::AssignmentStatement *preorder(IR::AssignmentStatement *assign) { + visit(assign->right, "right", 1); + visit(assign->left, "left", 0); + prune(); + return assign; + } + + public: + ReplaceIndexRefs(cstring iv, long v) : indexVar(iv), value(v) { forceClone = true; } +}; + +static long evalLoop(const IR::Expression *exp, cstring index, long val, bool &fail) { + if (auto *pe = exp->to()) { + if (pe->path->name != index) fail = true; + return val; + } else if (auto *k = exp->to()) { + return k->asLong(); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) <= evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) < evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) >= evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) > evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) == evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) != evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) + evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) - evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) * evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) / evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) % evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) << evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return evalLoop(e->left, index, val, fail) >> evalLoop(e->right, index, val, fail); + } else if (auto *e = exp->to()) { + return -evalLoop(e->expr, index, val, fail); + } else if (auto *e = exp->to()) { + return ~evalLoop(e->expr, index, val, fail); + } else if (auto *e = exp->to()) { + return !evalLoop(e->expr, index, val, fail); + } + fail = true; + return 0; +} + +bool UnrollLoops::findLoopBounds(IR::ForStatement *fstmt, loop_bounds_t &bounds) { + Pattern::Match v; + Pattern::Match k; + if (v.Relation(k).match(fstmt->condition)) { + auto d = resolveUnique(v->path->name, P4::ResolutionType::Any); + bounds.index = d ? d->to() : nullptr; + if (!bounds.index) return false; + auto &defs = defUse->getDefs(v); + const IR::AssignmentStatement *init = nullptr, *incr = nullptr; + for (auto *d : defs) { + bool ok = false; + for (auto *a : fstmt->init) { + if (a == d->parent->node) { + init = a->to(); + ok = true; + break; + } + } + for (auto *a : fstmt->updates) { + if (a == d->parent->node) { + incr = a->to(); + ok = true; + break; + } + } + if (!ok) return false; + } + if (!init || !incr) return false; + auto initval = init->right->to(); + if (!initval) return false; + bool fail = false; + for (long val = initval->asLong(); + evalLoop(fstmt->condition, bounds.index->name, val, fail) && !fail; + val = evalLoop(incr->right, bounds.index->name, val, fail)) { + if (bounds.indexes.size() > 1000) { + fail = true; + break; + } + bounds.indexes.push_back(val); + } + return !fail; + } + return false; +} + +bool UnrollLoops::findLoopBounds(IR::ForInStatement *fstmt, loop_bounds_t &bounds) { + if (auto range = fstmt->collection->to()) { + auto lo = range->left->to(); + auto hi = range->right->to(); + if (lo && hi) { + for (long i = lo->asLong(); i <= hi->asLong(); ++i) bounds.indexes.push_back(i); + if (!(bounds.index = fstmt->decl)) { + auto d = resolveUnique(fstmt->ref->path->name, P4::ResolutionType::Any); + BUG_CHECK(d && d->is(), "index is not a var?"); + bounds.index = d->to(); + } + return true; + } + } + return false; +} + +const IR::Statement *UnrollLoops::doUnroll(const loop_bounds_t &bounds, const IR::Statement *body, + const IR::IndexedVector *updates) { + RemoveBreakContinue rbc(nameGen); + body = body->apply(rbc, getChildContext()); + if (rbc.continueFlag) + body = new IR::BlockStatement({setFlag(rbc.continueFlag->name, false), body}); + auto *rv = new IR::BlockStatement(body->srcInfo); + if (auto *bs = body->to()) rv->annotations = bs->annotations; + if (rbc.breakFlag) rv->append(rbc.breakFlag); + if (rbc.continueFlag) rv->append(rbc.continueFlag); + if (rbc.breakFlag) rv->append(setFlag(rbc.breakFlag->name, false)); + IR::BlockStatement *blk = rv; + for (long indexval : bounds.indexes) { + ReplaceIndexRefs rir(bounds.index->name, indexval); + blk->append(body->apply(rir)); + if (rbc.breakFlag) { + auto newblk = new IR::BlockStatement; + auto cond = new IR::LNot(new IR::PathExpression(rbc.breakFlag->name)); + blk->append(new IR::IfStatement(cond, newblk, nullptr)); + blk = newblk; + } + if (updates) { + for (auto *u : *updates) { + auto *n = u->apply(rir)->to(); + BUG_CHECK(n, "unexpected nullptr"); + blk->append(n); + } + } + } + return rv; +} + +const IR::Statement *UnrollLoops::preorder(IR::ForStatement *fstmt) { + loop_bounds_t bounds; + if (findLoopBounds(fstmt, bounds)) { + LOG4("Unrolling loop" << Log::indent << Log::endl << fstmt << Log::unindent); + auto *rv = new IR::BlockStatement; + for (auto *i : fstmt->init) rv->append(i); + rv->append(doUnroll(bounds, fstmt->body, &fstmt->updates)); + LOG4("Unrolled loop" << Log::indent << Log::endl << rv << Log::unindent); + return rv; + } + return fstmt; +} + +const IR::Statement *UnrollLoops::preorder(IR::ForInStatement *fstmt) { + loop_bounds_t bounds; + if (findLoopBounds(fstmt, bounds)) { + LOG4("Unrolling loop" << Log::indent << Log::endl << fstmt << Log::unindent); + auto rv = doUnroll(bounds, fstmt->body); + LOG4("Unrolled loop" << Log::indent << Log::endl << rv << Log::unindent); + return rv; + } + return fstmt; +} +} // namespace P4 diff --git a/midend/unrollLoops.h b/midend/unrollLoops.h new file mode 100644 index 0000000000..40d9fb258f --- /dev/null +++ b/midend/unrollLoops.h @@ -0,0 +1,47 @@ +/* +Copyright 2024 Nvidia Corp. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#ifndef MIDEND_UNROLLLOOPS_H_ +#define MIDEND_UNROLLLOOPS_H_ + +#include "def_use.h" +#include "ir/ir.h" + +namespace P4 { + +class UnrollLoops : public Transform, public P4::ResolutionContext { + NameGenerator &nameGen; + const ComputeDefUse *defUse; + + struct loop_bounds_t { + const IR::Declaration_Variable *index = nullptr; + std::vector indexes; + }; + bool findLoopBounds(IR::ForStatement *, loop_bounds_t &); + bool findLoopBounds(IR::ForInStatement *, loop_bounds_t &); + const IR::Statement *doUnroll(const loop_bounds_t &, const IR::Statement *, + const IR::IndexedVector * = nullptr); + + const IR::Statement *preorder(IR::ForStatement *) override; + const IR::Statement *preorder(IR::ForInStatement *) override; + + public: + explicit UnrollLoops(NameGenerator &ng, const ComputeDefUse *du) : nameGen(ng), defUse(du) {} +}; + +} // namespace P4 + +#endif /* MIDEND_UNROLLLOOPS_H_ */ diff --git a/testdata/p4_16_errors/loop1-err.p4 b/testdata/p4_16_errors/loop1-err.p4 new file mode 100644 index 0000000000..233b1bdccf --- /dev/null +++ b/testdata/p4_16_errors/loop1-err.p4 @@ -0,0 +1,8 @@ + +action a1() { + break; +} + +action a2() { + continue; +} diff --git a/testdata/p4_16_errors/loop2-err.p4 b/testdata/p4_16_errors/loop2-err.p4 new file mode 100644 index 0000000000..eebc231ca5 --- /dev/null +++ b/testdata/p4_16_errors/loop2-err.p4 @@ -0,0 +1,9 @@ +extern void fn(in bit<8> c); + +control c() { + apply { + for (bit<8> a in 16w0..16w15) { + fn(a); + } + } +} diff --git a/testdata/p4_16_errors_outputs/enumCast.p4-stderr b/testdata/p4_16_errors_outputs/enumCast.p4-stderr index 7ed8c2c140..c20982caa4 100644 --- a/testdata/p4_16_errors_outputs/enumCast.p4-stderr +++ b/testdata/p4_16_errors_outputs/enumCast.p4-stderr @@ -1,6 +1,6 @@ enumCast.p4(26): [--Werror=type-error] error: 'y': values of type 'int' cannot be implicitly cast to type 'X' X y = 1; // Error: no implicit cast to enum - ^^^^^^^^ + ^^^^^^^ enumCast.p4(3) enum bit<32> X { ^ diff --git a/testdata/p4_16_errors_outputs/implicit.p4-stderr b/testdata/p4_16_errors_outputs/implicit.p4-stderr index fd9e225d6f..06ef4e6ac9 100644 --- a/testdata/p4_16_errors_outputs/implicit.p4-stderr +++ b/testdata/p4_16_errors_outputs/implicit.p4-stderr @@ -1,6 +1,6 @@ implicit.p4(19): [--Werror=type-error] error: 'b' bit<32> b = 32s1; - ^^^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^^^ ---- Actual error: Cannot cast implicitly type 'int<32>' to type 'bit<32>' ---- Originating from: diff --git a/testdata/p4_16_errors_outputs/issue2335.p4-stderr b/testdata/p4_16_errors_outputs/issue2335.p4-stderr index 49778f3a8c..e1cdfa42f6 100644 --- a/testdata/p4_16_errors_outputs/issue2335.p4-stderr +++ b/testdata/p4_16_errors_outputs/issue2335.p4-stderr @@ -1,6 +1,6 @@ issue2335.p4(3): [--Werror=type-error] error: x: Cannot declare variables with type int int x = 0; - ^^^^^^^^^^ + ^^^^^^^^^ issue2335.p4(3) int x = 0; ^^^ diff --git a/testdata/p4_16_errors_outputs/issue2544_shadowing1.p4-stderr b/testdata/p4_16_errors_outputs/issue2544_shadowing1.p4-stderr index 1c2492083c..78303fdd79 100644 --- a/testdata/p4_16_errors_outputs/issue2544_shadowing1.p4-stderr +++ b/testdata/p4_16_errors_outputs/issue2544_shadowing1.p4-stderr @@ -1,6 +1,6 @@ issue2544_shadowing1.p4(25): [--Werror=shadow] error: declaration of 'h' shadows a parameter 'h' Headers h = h; - ^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^ issue2544_shadowing1.p4(23) control ingress(inout Headers h) { ^ diff --git a/testdata/p4_16_errors_outputs/issue3359.p4-stderr b/testdata/p4_16_errors_outputs/issue3359.p4-stderr index a9edbe5fcb..2f40cf8b9f 100644 --- a/testdata/p4_16_errors_outputs/issue3359.p4-stderr +++ b/testdata/p4_16_errors_outputs/issue3359.p4-stderr @@ -1,12 +1,12 @@ issue3359.p4(14): [--Werror=type-error] error: t: cannot declare variables of type 'parser mypt' (consider using an instantiation) mypt t = MyParser(); - ^^^^^^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^^^^^^ issue3359.p4(1) parser mypt(in bit tt); ^^^^ issue3359.p4(25): [--Werror=type-error] error: t: cannot declare variables of type 'parser mypt' (consider using an instantiation) mypt t; - ^^^^^^^ + ^^^^^^ issue3359.p4(1) parser mypt(in bit tt); ^^^^ diff --git a/testdata/p4_16_errors_outputs/issue345.p4-stderr b/testdata/p4_16_errors_outputs/issue345.p4-stderr index 486207456c..61593424d2 100644 --- a/testdata/p4_16_errors_outputs/issue345.p4-stderr +++ b/testdata/p4_16_errors_outputs/issue345.p4-stderr @@ -1,6 +1,6 @@ issue345.p4(19): [--Werror=type-error] error: 'h' H h = 0; - ^^^^^^^^ + ^^^^^^^ ---- Actual error: issue345.p4(17): 'int' type can only be unified with 'int', 'bit<>', or 'signed<>' types, not with 'H' control C() { diff --git a/testdata/p4_16_errors_outputs/issue394.p4-stderr b/testdata/p4_16_errors_outputs/issue394.p4-stderr index 302b50fbe9..ec2710d5cd 100644 --- a/testdata/p4_16_errors_outputs/issue394.p4-stderr +++ b/testdata/p4_16_errors_outputs/issue394.p4-stderr @@ -1,6 +1,6 @@ issue394.p4(19): [--Werror=type-error] error: c: cannot declare variables of type 'C' (consider using an instantiation) C c; - ^^^^ + ^^^ issue394.p4(16) extern C { bool get(); } ^ diff --git a/testdata/p4_16_errors_outputs/issue561-1.p4-stderr b/testdata/p4_16_errors_outputs/issue561-1.p4-stderr index 9868266238..a4688f5cf6 100644 --- a/testdata/p4_16_errors_outputs/issue561-1.p4-stderr +++ b/testdata/p4_16_errors_outputs/issue561-1.p4-stderr @@ -1,6 +1,6 @@ issue561-1.p4(29): [--Werror=type-error] error: 'u' U u = { { 10 }, { 20 } }; // illegal to initialize unions - ^^^^^^^^^^^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^^^^^^^^^^^ ---- Actual error: issue561-1.p4(29): Cannot cast implicitly type 'tuple, tuple>' to type 'header_union U' U u = { { 10 }, { 20 } }; // illegal to initialize unions diff --git a/testdata/p4_16_errors_outputs/issue807.p4-stderr b/testdata/p4_16_errors_outputs/issue807.p4-stderr index 5106645460..957820677f 100644 --- a/testdata/p4_16_errors_outputs/issue807.p4-stderr +++ b/testdata/p4_16_errors_outputs/issue807.p4-stderr @@ -6,7 +6,7 @@ control C2(); ^^ issue807.p4(20): [--Werror=type-error] error: c2: cannot declare variables of type 'control C2' (consider using an instantiation) C2 c2 = e.get2(); - ^^^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^^^ issue807.p4(5) control C2(); ^^ @@ -18,7 +18,7 @@ control C1(); ^^ issue807.p4(26): [--Werror=type-error] error: c1: cannot declare variables of type 'control C1' (consider using an instantiation) C1 c1 = e.get1(); - ^^^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^^^ issue807.p4(4) control C1(); ^^ diff --git a/testdata/p4_16_errors_outputs/issue816-1.p4-stderr b/testdata/p4_16_errors_outputs/issue816-1.p4-stderr index 9fd0cabf1a..13dbda0ebe 100644 --- a/testdata/p4_16_errors_outputs/issue816-1.p4-stderr +++ b/testdata/p4_16_errors_outputs/issue816-1.p4-stderr @@ -3,7 +3,7 @@ control MyC1()(P p) { ^ issue816-1.p4(25): [--Werror=type-error] error: c1: cannot declare variables of type 'control C' (consider using an instantiation) C c1 = MyC1(p); - ^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^ issue816-1.p4(4) control C(); ^ @@ -12,7 +12,7 @@ control MyC2()(P p) { ^ issue816-1.p4(26): [--Werror=type-error] error: c2: cannot declare variables of type 'control C' (consider using an instantiation) C c2 = MyC2(p); - ^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^ issue816-1.p4(4) control C(); ^ diff --git a/testdata/p4_16_errors_outputs/loop1-err.p4 b/testdata/p4_16_errors_outputs/loop1-err.p4 new file mode 100644 index 0000000000..9f9521522e --- /dev/null +++ b/testdata/p4_16_errors_outputs/loop1-err.p4 @@ -0,0 +1,6 @@ +action a1() { + break; +} +action a2() { + continue; +} diff --git a/testdata/p4_16_errors_outputs/loop1-err.p4-stderr b/testdata/p4_16_errors_outputs/loop1-err.p4-stderr new file mode 100644 index 0000000000..52f1b04dbf --- /dev/null +++ b/testdata/p4_16_errors_outputs/loop1-err.p4-stderr @@ -0,0 +1,6 @@ +loop1-err.p4(3): [--Werror=invalid] error: break: break statement must be used in the context of a for statement. + break; + ^^^^^ +loop1-err.p4(7): [--Werror=invalid] error: continue: continue statement must be used in the context of a for statement. + continue; + ^^^^^^^^ diff --git a/testdata/p4_16_errors_outputs/loop2-err.p4 b/testdata/p4_16_errors_outputs/loop2-err.p4 new file mode 100644 index 0000000000..51f0917d98 --- /dev/null +++ b/testdata/p4_16_errors_outputs/loop2-err.p4 @@ -0,0 +1,9 @@ +extern void fn(in bit<8> c); +control c() { + apply { + for (bit<8> a in 16w0 .. 16w15) { + fn(a); + } + } +} + diff --git a/testdata/p4_16_errors_outputs/loop2-err.p4-stderr b/testdata/p4_16_errors_outputs/loop2-err.p4-stderr new file mode 100644 index 0000000000..3589fc9fb6 --- /dev/null +++ b/testdata/p4_16_errors_outputs/loop2-err.p4-stderr @@ -0,0 +1,9 @@ +loop2-err.p4(5): [--Werror=type-error] error: 'ForInStatement' + for (bit<8> a in 16w0..16w15) { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ---- Actual error: + Cannot cast implicitly type 'bit<16>' to type 'bit<8>' + ---- Originating from: +loop2-err.p4(5): Source expression '16w0' produces a result of type 'bit<16>' which cannot be assigned to a left-value with type 'bit<8>' + for (bit<8> a in 16w0..16w15) { + ^^^^ diff --git a/testdata/p4_16_errors_outputs/signs.p4-stderr b/testdata/p4_16_errors_outputs/signs.p4-stderr index d4176848e1..b2992cc3fb 100644 --- a/testdata/p4_16_errors_outputs/signs.p4-stderr +++ b/testdata/p4_16_errors_outputs/signs.p4-stderr @@ -1,6 +1,6 @@ signs.p4(18): [--Werror=type-error] error: 'b' int<8> b = 8w0; - ^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^ ---- Actual error: Cannot cast implicitly type 'bit<8>' to type 'int<8>' ---- Originating from: diff --git a/testdata/p4_16_errors_outputs/string-e1.p4-stderr b/testdata/p4_16_errors_outputs/string-e1.p4-stderr index a037200b76..f11a3bd462 100644 --- a/testdata/p4_16_errors_outputs/string-e1.p4-stderr +++ b/testdata/p4_16_errors_outputs/string-e1.p4-stderr @@ -9,7 +9,7 @@ struct S { ^ string-e1.p4(7): [--Werror=type-error] error: v: Cannot declare variables with type string string v; - ^^^^^^^^^ + ^^^^^^^^ string-e1.p4(7) string v; ^^^^^^ diff --git a/testdata/p4_16_samples/forloop1.p4 b/testdata/p4_16_samples/forloop1.p4 new file mode 100644 index 0000000000..e6cc931708 --- /dev/null +++ b/testdata/p4_16_samples/forloop1.p4 @@ -0,0 +1,32 @@ +#include +control generic(inout M m); +package top(generic c); + +header t1 { + bit<32> f1; + bit<16> h1; + bit<8> b1; + bit<8> cnt; +} + +header t2 { + bit<32> x; +} + +struct headers_t { + t1 head; + t2[8] stack; +} + +control c(inout headers_t hdrs) { + apply { + for (t2 v in hdrs.stack) { + hdrs.head.f1 = hdrs.head.f1 + v.x; + } + for (bit<8> v = 0, bit<16> x = 1; v < hdrs.head.cnt; v = v + 1, x = x << 1) { + hdrs.head.h1 = hdrs.head.h1 +x; + } + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples/forloop2.p4 b/testdata/p4_16_samples/forloop2.p4 new file mode 100644 index 0000000000..a7eb53dc0b --- /dev/null +++ b/testdata/p4_16_samples/forloop2.p4 @@ -0,0 +1,31 @@ +#include +control generic(inout M m); +package top(generic c); + +header t1 { + bit<64> v; +} + +struct headers_t { + t1 t1; +} + +bit<64> _popcount(in bit<64> val) { + bit<64> n = 0; + bit<64> v = val; + for (bit<64> popcnti in 1 .. 64w63) { + if (v == 0) + return n; + n = n + 1; + v = v & (v - 1); + } + return n; +} + +control c(inout headers_t hdrs) { + apply { + hdrs.t1.v = _popcount(hdrs.t1.v); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples/forloop3.p4 b/testdata/p4_16_samples/forloop3.p4 new file mode 100644 index 0000000000..cde8571fd2 --- /dev/null +++ b/testdata/p4_16_samples/forloop3.p4 @@ -0,0 +1,50 @@ +#include +control generic(inout M m); +package top(generic c); + +extern T foo(in T x); + +header t1 { + bit<32> x; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0(bit<8> x, bit<8> y) { + bit<8> idx = 255; + for (bit<8> i1 in 0 .. x) { + for (bit<8> j in i1 .. y) { + idx = foo(j); + if (idx == 255) + break; + } + } + } + + action a1(bit<8> x, bit<8> y) { + bit<8> idx = 255; + for (bit<8> i in 0 .. x) { + for (bit<8> j in 0 .. y) { + idx = foo(j); + if (idx == 255) { + continue; + } + idx = foo(i); + } + } + } + + table test { + key = { hdrs.t1.x: exact; } + actions = { a0; a1; } + } + + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples/forloop4.p4 b/testdata/p4_16_samples/forloop4.p4 new file mode 100644 index 0000000000..22a175b144 --- /dev/null +++ b/testdata/p4_16_samples/forloop4.p4 @@ -0,0 +1,66 @@ +#include +control generic(inout M m); +package top(generic c); + +header t1 { + bit<32> x; +} + +struct headers_t { + t1 t1; +} + +bit<8> foo(in bit<8> aa, in bit<8> bb) { + // Do some magic to ensure aa / bb will not be simplified + +return aa - bb; +} + +control c(inout headers_t hdrs) { + action a0(bit<8> x, bit<8> y) { + // Simple loops: with and w/o use of index variable. + for (bit<8> i in 1 .. (x+y)) { + foo(x, y); + } + + for (bit<8> i in 1 .. (x+y)) { + foo(x, y + i); + } + + // And with constant range as well + for (bit<8> i in 8w1 .. 42) { + foo(x, y + i); + } + } + + action a1(bit<8> x, bit<8> y) { + // Nested loops + for (bit<8> i in 1 .. x) { + for (bit<8> j in i .. y) + foo(x, y + i); + } + } + + // Scope test + action a2(bit<8> x, bit<8> y) { + bit<8> i = 10; + for (bit<8> i in 1 .. x) { + foo(x, y + i); + } + + for (bit<8> k in i .. (x+y)) { + foo(i, 2*i+x); + } + } + + table test { + key = { hdrs.t1.x: exact; } + actions = { a0; a1; a2; } + } + + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples/forloop5.p4 b/testdata/p4_16_samples/forloop5.p4 new file mode 100644 index 0000000000..9f7df861cb --- /dev/null +++ b/testdata/p4_16_samples/forloop5.p4 @@ -0,0 +1,30 @@ +#include +control generic(inout M m); +package top(generic c); + + +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0() { + bit<32> result = 0; + for (bit<8> i = 0; i < 4; i = i + 1) { + result = result << 8; + result = result + (((hdrs.t1.x >> 8*i) + (hdrs.t1.y >> 8*i)) & 0xff); + } + hdrs.t1.x = result; + } + + apply { + a0(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples/forloop6.p4 b/testdata/p4_16_samples/forloop6.p4 new file mode 100644 index 0000000000..53be3943fe --- /dev/null +++ b/testdata/p4_16_samples/forloop6.p4 @@ -0,0 +1,38 @@ +#include +control generic(inout M m); +package top(generic c); + + +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0(bit<8> m) { + bit<32> result = 0; + bit<8> mask = m; + for (bit<8> i = 0; i < 32; i = i + 4, mask = mask >> 1) { + if (mask == 0) break; + if (mask[0:0] == 0) continue; + result = result + ((hdrs.t1.y >> i) & 0xf); + } + hdrs.t1.y = result; + } + + table test { + key = { hdrs.t1.x: exact; } + actions = { a0; } + } + + + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples/forloop7.p4 b/testdata/p4_16_samples/forloop7.p4 new file mode 100644 index 0000000000..5e2cc911d8 --- /dev/null +++ b/testdata/p4_16_samples/forloop7.p4 @@ -0,0 +1,41 @@ +#include +control generic(inout M m); +package top(generic c); + +extern bool fn(in bit<16> a, in bit<16> b); + +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0(bit<8> m) { + for (bit<16> a in 1..2) { + fn(a, 0); + for (bit<16> b in 1..2) { + if (fn(a, b)) continue; + return; + } + fn(a, 3); + fn(a, 4); + } + fn(3, 3); + } + + table test { + key = { hdrs.t1.x: exact; } + actions = { a0; } + } + + + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/decl.p4-stderr b/testdata/p4_16_samples_outputs/decl.p4-stderr index 0cc165419a..5ebbd0a6fd 100644 --- a/testdata/p4_16_samples_outputs/decl.p4-stderr +++ b/testdata/p4_16_samples_outputs/decl.p4-stderr @@ -1,15 +1,15 @@ decl.p4(33): [--Wwarn=shadow] warning: 'y' shadows 'y' bit y; - ^^^^^^ + ^^^^^ decl.p4(30) bit y; - ^^^^^^ + ^^^^^ decl.p4(37): [--Wwarn=shadow] warning: 'y' shadows 'y' bit y; - ^^^^^^ + ^^^^^ decl.p4(33) bit y; - ^^^^^^ + ^^^^^ decl.p4(17): [--Wwarn=unused] warning: Control p is not used; removing control p(in bit y_0) ^ diff --git a/testdata/p4_16_samples_outputs/forloop1-first.p4 b/testdata/p4_16_samples_outputs/forloop1-first.p4 new file mode 100644 index 0000000000..06d8b1bdde --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop1-first.p4 @@ -0,0 +1,32 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> f1; + bit<16> h1; + bit<8> b1; + bit<8> cnt; +} + +header t2 { + bit<32> x; +} + +struct headers_t { + t1 head; + t2[8] stack; +} + +control c(inout headers_t hdrs) { + apply { + for (t2 v in hdrs.stack) { + hdrs.head.f1 = hdrs.head.f1 + v.x; + } + for (bit<8> v = 8w0, bit<16> x = 16w1; v < hdrs.head.cnt; v = v + 8w1, x = x << 1) { + hdrs.head.h1 = hdrs.head.h1 + x; + } + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop1-frontend.p4 b/testdata/p4_16_samples_outputs/forloop1-frontend.p4 new file mode 100644 index 0000000000..fd01b30f6f --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop1-frontend.p4 @@ -0,0 +1,35 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> f1; + bit<16> h1; + bit<8> b1; + bit<8> cnt; +} + +header t2 { + bit<32> x; +} + +struct headers_t { + t1 head; + t2[8] stack; +} + +control c(inout headers_t hdrs) { + @name("c.v") t2 v_0; + @name("c.v") bit<8> v_1; + @name("c.x") bit<16> x_0; + apply { + for (v_0 in hdrs.stack) { + hdrs.head.f1 = hdrs.head.f1 + v_0.x; + } + for (v_1 = 8w0, x_0 = 16w1; v_1 < hdrs.head.cnt; v_1 = v_1 + 8w1, x_0 = x_0 << 1) { + hdrs.head.h1 = hdrs.head.h1 + x_0; + } + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop1-midend.p4 b/testdata/p4_16_samples_outputs/forloop1-midend.p4 new file mode 100644 index 0000000000..4cb395de10 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop1-midend.p4 @@ -0,0 +1,53 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> f1; + bit<16> h1; + bit<8> b1; + bit<8> cnt; +} + +header t2 { + bit<32> x; +} + +struct headers_t { + t1 head; + t2[8] stack; +} + +control c(inout headers_t hdrs) { + @name("c.v") t2 v_0; + @name("c.v") bit<8> v_1; + @name("c.x") bit<16> x_0; + @hidden action forloop1l24() { + hdrs.head.f1 = hdrs.head.f1 + v_0.x; + } + @hidden action forloop1l27() { + hdrs.head.h1 = hdrs.head.h1 + x_0; + } + @hidden table tbl_forloop1l24 { + actions = { + forloop1l24(); + } + const default_action = forloop1l24(); + } + @hidden table tbl_forloop1l27 { + actions = { + forloop1l27(); + } + const default_action = forloop1l27(); + } + apply { + for (v_0 in hdrs.stack) { + tbl_forloop1l24.apply(); + } + for (v_1 = 8w0, x_0 = 16w1; v_1 < hdrs.head.cnt; v_1 = v_1 + 8w1, x_0 = x_0 << 1) { + tbl_forloop1l27.apply(); + } + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop1.p4 b/testdata/p4_16_samples_outputs/forloop1.p4 new file mode 100644 index 0000000000..74b83a41b4 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop1.p4 @@ -0,0 +1,32 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> f1; + bit<16> h1; + bit<8> b1; + bit<8> cnt; +} + +header t2 { + bit<32> x; +} + +struct headers_t { + t1 head; + t2[8] stack; +} + +control c(inout headers_t hdrs) { + apply { + for (t2 v in hdrs.stack) { + hdrs.head.f1 = hdrs.head.f1 + v.x; + } + for (bit<8> v = 0, bit<16> x = 1; v < hdrs.head.cnt; v = v + 1, x = x << 1) { + hdrs.head.h1 = hdrs.head.h1 + x; + } + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop1.p4-stderr b/testdata/p4_16_samples_outputs/forloop1.p4-stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/p4_16_samples_outputs/forloop2-first.p4 b/testdata/p4_16_samples_outputs/forloop2-first.p4 new file mode 100644 index 0000000000..b28726dbfa --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop2-first.p4 @@ -0,0 +1,31 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<64> v; +} + +struct headers_t { + t1 t1; +} + +bit<64> _popcount(in bit<64> val) { + bit<64> n = 64w0; + bit<64> v = val; + for (bit<64> popcnti in 64w1 .. 64w63) { + if (v == 64w0) { + return n; + } + n = n + 64w1; + v = v & v + 64w18446744073709551615; + } + return n; +} +control c(inout headers_t hdrs) { + apply { + hdrs.t1.v = _popcount(hdrs.t1.v); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop2-frontend.p4 b/testdata/p4_16_samples_outputs/forloop2-frontend.p4 new file mode 100644 index 0000000000..d0b6a39cfa --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop2-frontend.p4 @@ -0,0 +1,47 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<64> v; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.val_0") bit<64> val; + @name("c.hasReturned") bool hasReturned; + @name("c.retval") bit<64> retval; + @name("c.n") bit<64> n_0; + @name("c.v") bit<64> v_0; + @name("c.popcnti") bit<64> popcnti_0; + apply { + val = hdrs.t1.v; + hasReturned = false; + n_0 = 64w0; + v_0 = val; + for (popcnti_0 in 64w1 .. 64w63) { + if (v_0 == 64w0) { + hasReturned = true; + retval = n_0; + break; + } + if (hasReturned) { + ; + } else { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + } + if (hasReturned) { + ; + } else { + retval = n_0; + } + hdrs.t1.v = retval; + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop2-midend.p4 b/testdata/p4_16_samples_outputs/forloop2-midend.p4 new file mode 100644 index 0000000000..5a7261175e --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop2-midend.p4 @@ -0,0 +1,2270 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<64> v; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.hasReturned") bool hasReturned; + @name("c.retval") bit<64> retval; + @name("c.n") bit<64> n_0; + @name("c.v") bit<64> v_0; + bool breakFlag; + @hidden action forloop2l18() { + hasReturned = true; + retval = 64w0; + breakFlag = true; + } + @hidden action act() { + breakFlag = false; + } + @hidden action forloop2l19() { + n_0 = 64w1; + v_0 = hdrs.t1.v & hdrs.t1.v + 64w18446744073709551615; + } + @hidden action forloop2l18_0() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_0() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_1() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_1() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_2() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_2() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_3() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_3() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_4() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_4() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_5() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_5() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_6() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_6() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_7() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_7() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_8() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_8() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_9() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_9() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_10() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_10() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_11() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_11() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_12() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_12() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_13() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_13() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_14() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_14() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_15() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_15() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_16() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_16() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_17() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_17() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_18() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_18() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_19() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_19() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_20() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_20() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_21() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_21() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_22() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_22() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_23() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_23() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_24() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_24() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_25() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_25() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_26() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_26() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_27() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_27() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_28() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_28() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_29() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_29() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_30() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_30() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_31() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_31() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_32() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_32() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_33() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_33() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_34() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_34() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_35() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_35() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_36() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_36() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_37() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_37() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_38() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_38() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_39() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_39() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_40() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_40() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_41() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_41() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_42() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_42() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_43() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_43() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_44() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_44() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_45() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_45() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_46() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_46() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_47() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_47() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_48() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_48() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_49() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_49() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_50() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_50() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_51() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_51() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_52() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_52() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_53() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_53() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_54() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_54() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_55() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_55() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_56() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_56() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_57() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_57() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_58() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_58() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_59() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_59() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_60() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_60() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l18_61() { + hasReturned = true; + retval = n_0; + breakFlag = true; + } + @hidden action forloop2l19_61() { + n_0 = n_0 + 64w1; + v_0 = v_0 & v_0 + 64w18446744073709551615; + } + @hidden action forloop2l14() { + hasReturned = false; + n_0 = 64w0; + v_0 = hdrs.t1.v; + } + @hidden action forloop2l22() { + retval = n_0; + } + @hidden action forloop2l27() { + hdrs.t1.v = retval; + } + @hidden table tbl_forloop2l14 { + actions = { + forloop2l14(); + } + const default_action = forloop2l14(); + } + @hidden table tbl_act { + actions = { + act(); + } + const default_action = act(); + } + @hidden table tbl_forloop2l18 { + actions = { + forloop2l18(); + } + const default_action = forloop2l18(); + } + @hidden table tbl_forloop2l19 { + actions = { + forloop2l19(); + } + const default_action = forloop2l19(); + } + @hidden table tbl_forloop2l18_0 { + actions = { + forloop2l18_0(); + } + const default_action = forloop2l18_0(); + } + @hidden table tbl_forloop2l19_0 { + actions = { + forloop2l19_0(); + } + const default_action = forloop2l19_0(); + } + @hidden table tbl_forloop2l18_1 { + actions = { + forloop2l18_1(); + } + const default_action = forloop2l18_1(); + } + @hidden table tbl_forloop2l19_1 { + actions = { + forloop2l19_1(); + } + const default_action = forloop2l19_1(); + } + @hidden table tbl_forloop2l18_2 { + actions = { + forloop2l18_2(); + } + const default_action = forloop2l18_2(); + } + @hidden table tbl_forloop2l19_2 { + actions = { + forloop2l19_2(); + } + const default_action = forloop2l19_2(); + } + @hidden table tbl_forloop2l18_3 { + actions = { + forloop2l18_3(); + } + const default_action = forloop2l18_3(); + } + @hidden table tbl_forloop2l19_3 { + actions = { + forloop2l19_3(); + } + const default_action = forloop2l19_3(); + } + @hidden table tbl_forloop2l18_4 { + actions = { + forloop2l18_4(); + } + const default_action = forloop2l18_4(); + } + @hidden table tbl_forloop2l19_4 { + actions = { + forloop2l19_4(); + } + const default_action = forloop2l19_4(); + } + @hidden table tbl_forloop2l18_5 { + actions = { + forloop2l18_5(); + } + const default_action = forloop2l18_5(); + } + @hidden table tbl_forloop2l19_5 { + actions = { + forloop2l19_5(); + } + const default_action = forloop2l19_5(); + } + @hidden table tbl_forloop2l18_6 { + actions = { + forloop2l18_6(); + } + const default_action = forloop2l18_6(); + } + @hidden table tbl_forloop2l19_6 { + actions = { + forloop2l19_6(); + } + const default_action = forloop2l19_6(); + } + @hidden table tbl_forloop2l18_7 { + actions = { + forloop2l18_7(); + } + const default_action = forloop2l18_7(); + } + @hidden table tbl_forloop2l19_7 { + actions = { + forloop2l19_7(); + } + const default_action = forloop2l19_7(); + } + @hidden table tbl_forloop2l18_8 { + actions = { + forloop2l18_8(); + } + const default_action = forloop2l18_8(); + } + @hidden table tbl_forloop2l19_8 { + actions = { + forloop2l19_8(); + } + const default_action = forloop2l19_8(); + } + @hidden table tbl_forloop2l18_9 { + actions = { + forloop2l18_9(); + } + const default_action = forloop2l18_9(); + } + @hidden table tbl_forloop2l19_9 { + actions = { + forloop2l19_9(); + } + const default_action = forloop2l19_9(); + } + @hidden table tbl_forloop2l18_10 { + actions = { + forloop2l18_10(); + } + const default_action = forloop2l18_10(); + } + @hidden table tbl_forloop2l19_10 { + actions = { + forloop2l19_10(); + } + const default_action = forloop2l19_10(); + } + @hidden table tbl_forloop2l18_11 { + actions = { + forloop2l18_11(); + } + const default_action = forloop2l18_11(); + } + @hidden table tbl_forloop2l19_11 { + actions = { + forloop2l19_11(); + } + const default_action = forloop2l19_11(); + } + @hidden table tbl_forloop2l18_12 { + actions = { + forloop2l18_12(); + } + const default_action = forloop2l18_12(); + } + @hidden table tbl_forloop2l19_12 { + actions = { + forloop2l19_12(); + } + const default_action = forloop2l19_12(); + } + @hidden table tbl_forloop2l18_13 { + actions = { + forloop2l18_13(); + } + const default_action = forloop2l18_13(); + } + @hidden table tbl_forloop2l19_13 { + actions = { + forloop2l19_13(); + } + const default_action = forloop2l19_13(); + } + @hidden table tbl_forloop2l18_14 { + actions = { + forloop2l18_14(); + } + const default_action = forloop2l18_14(); + } + @hidden table tbl_forloop2l19_14 { + actions = { + forloop2l19_14(); + } + const default_action = forloop2l19_14(); + } + @hidden table tbl_forloop2l18_15 { + actions = { + forloop2l18_15(); + } + const default_action = forloop2l18_15(); + } + @hidden table tbl_forloop2l19_15 { + actions = { + forloop2l19_15(); + } + const default_action = forloop2l19_15(); + } + @hidden table tbl_forloop2l18_16 { + actions = { + forloop2l18_16(); + } + const default_action = forloop2l18_16(); + } + @hidden table tbl_forloop2l19_16 { + actions = { + forloop2l19_16(); + } + const default_action = forloop2l19_16(); + } + @hidden table tbl_forloop2l18_17 { + actions = { + forloop2l18_17(); + } + const default_action = forloop2l18_17(); + } + @hidden table tbl_forloop2l19_17 { + actions = { + forloop2l19_17(); + } + const default_action = forloop2l19_17(); + } + @hidden table tbl_forloop2l18_18 { + actions = { + forloop2l18_18(); + } + const default_action = forloop2l18_18(); + } + @hidden table tbl_forloop2l19_18 { + actions = { + forloop2l19_18(); + } + const default_action = forloop2l19_18(); + } + @hidden table tbl_forloop2l18_19 { + actions = { + forloop2l18_19(); + } + const default_action = forloop2l18_19(); + } + @hidden table tbl_forloop2l19_19 { + actions = { + forloop2l19_19(); + } + const default_action = forloop2l19_19(); + } + @hidden table tbl_forloop2l18_20 { + actions = { + forloop2l18_20(); + } + const default_action = forloop2l18_20(); + } + @hidden table tbl_forloop2l19_20 { + actions = { + forloop2l19_20(); + } + const default_action = forloop2l19_20(); + } + @hidden table tbl_forloop2l18_21 { + actions = { + forloop2l18_21(); + } + const default_action = forloop2l18_21(); + } + @hidden table tbl_forloop2l19_21 { + actions = { + forloop2l19_21(); + } + const default_action = forloop2l19_21(); + } + @hidden table tbl_forloop2l18_22 { + actions = { + forloop2l18_22(); + } + const default_action = forloop2l18_22(); + } + @hidden table tbl_forloop2l19_22 { + actions = { + forloop2l19_22(); + } + const default_action = forloop2l19_22(); + } + @hidden table tbl_forloop2l18_23 { + actions = { + forloop2l18_23(); + } + const default_action = forloop2l18_23(); + } + @hidden table tbl_forloop2l19_23 { + actions = { + forloop2l19_23(); + } + const default_action = forloop2l19_23(); + } + @hidden table tbl_forloop2l18_24 { + actions = { + forloop2l18_24(); + } + const default_action = forloop2l18_24(); + } + @hidden table tbl_forloop2l19_24 { + actions = { + forloop2l19_24(); + } + const default_action = forloop2l19_24(); + } + @hidden table tbl_forloop2l18_25 { + actions = { + forloop2l18_25(); + } + const default_action = forloop2l18_25(); + } + @hidden table tbl_forloop2l19_25 { + actions = { + forloop2l19_25(); + } + const default_action = forloop2l19_25(); + } + @hidden table tbl_forloop2l18_26 { + actions = { + forloop2l18_26(); + } + const default_action = forloop2l18_26(); + } + @hidden table tbl_forloop2l19_26 { + actions = { + forloop2l19_26(); + } + const default_action = forloop2l19_26(); + } + @hidden table tbl_forloop2l18_27 { + actions = { + forloop2l18_27(); + } + const default_action = forloop2l18_27(); + } + @hidden table tbl_forloop2l19_27 { + actions = { + forloop2l19_27(); + } + const default_action = forloop2l19_27(); + } + @hidden table tbl_forloop2l18_28 { + actions = { + forloop2l18_28(); + } + const default_action = forloop2l18_28(); + } + @hidden table tbl_forloop2l19_28 { + actions = { + forloop2l19_28(); + } + const default_action = forloop2l19_28(); + } + @hidden table tbl_forloop2l18_29 { + actions = { + forloop2l18_29(); + } + const default_action = forloop2l18_29(); + } + @hidden table tbl_forloop2l19_29 { + actions = { + forloop2l19_29(); + } + const default_action = forloop2l19_29(); + } + @hidden table tbl_forloop2l18_30 { + actions = { + forloop2l18_30(); + } + const default_action = forloop2l18_30(); + } + @hidden table tbl_forloop2l19_30 { + actions = { + forloop2l19_30(); + } + const default_action = forloop2l19_30(); + } + @hidden table tbl_forloop2l18_31 { + actions = { + forloop2l18_31(); + } + const default_action = forloop2l18_31(); + } + @hidden table tbl_forloop2l19_31 { + actions = { + forloop2l19_31(); + } + const default_action = forloop2l19_31(); + } + @hidden table tbl_forloop2l18_32 { + actions = { + forloop2l18_32(); + } + const default_action = forloop2l18_32(); + } + @hidden table tbl_forloop2l19_32 { + actions = { + forloop2l19_32(); + } + const default_action = forloop2l19_32(); + } + @hidden table tbl_forloop2l18_33 { + actions = { + forloop2l18_33(); + } + const default_action = forloop2l18_33(); + } + @hidden table tbl_forloop2l19_33 { + actions = { + forloop2l19_33(); + } + const default_action = forloop2l19_33(); + } + @hidden table tbl_forloop2l18_34 { + actions = { + forloop2l18_34(); + } + const default_action = forloop2l18_34(); + } + @hidden table tbl_forloop2l19_34 { + actions = { + forloop2l19_34(); + } + const default_action = forloop2l19_34(); + } + @hidden table tbl_forloop2l18_35 { + actions = { + forloop2l18_35(); + } + const default_action = forloop2l18_35(); + } + @hidden table tbl_forloop2l19_35 { + actions = { + forloop2l19_35(); + } + const default_action = forloop2l19_35(); + } + @hidden table tbl_forloop2l18_36 { + actions = { + forloop2l18_36(); + } + const default_action = forloop2l18_36(); + } + @hidden table tbl_forloop2l19_36 { + actions = { + forloop2l19_36(); + } + const default_action = forloop2l19_36(); + } + @hidden table tbl_forloop2l18_37 { + actions = { + forloop2l18_37(); + } + const default_action = forloop2l18_37(); + } + @hidden table tbl_forloop2l19_37 { + actions = { + forloop2l19_37(); + } + const default_action = forloop2l19_37(); + } + @hidden table tbl_forloop2l18_38 { + actions = { + forloop2l18_38(); + } + const default_action = forloop2l18_38(); + } + @hidden table tbl_forloop2l19_38 { + actions = { + forloop2l19_38(); + } + const default_action = forloop2l19_38(); + } + @hidden table tbl_forloop2l18_39 { + actions = { + forloop2l18_39(); + } + const default_action = forloop2l18_39(); + } + @hidden table tbl_forloop2l19_39 { + actions = { + forloop2l19_39(); + } + const default_action = forloop2l19_39(); + } + @hidden table tbl_forloop2l18_40 { + actions = { + forloop2l18_40(); + } + const default_action = forloop2l18_40(); + } + @hidden table tbl_forloop2l19_40 { + actions = { + forloop2l19_40(); + } + const default_action = forloop2l19_40(); + } + @hidden table tbl_forloop2l18_41 { + actions = { + forloop2l18_41(); + } + const default_action = forloop2l18_41(); + } + @hidden table tbl_forloop2l19_41 { + actions = { + forloop2l19_41(); + } + const default_action = forloop2l19_41(); + } + @hidden table tbl_forloop2l18_42 { + actions = { + forloop2l18_42(); + } + const default_action = forloop2l18_42(); + } + @hidden table tbl_forloop2l19_42 { + actions = { + forloop2l19_42(); + } + const default_action = forloop2l19_42(); + } + @hidden table tbl_forloop2l18_43 { + actions = { + forloop2l18_43(); + } + const default_action = forloop2l18_43(); + } + @hidden table tbl_forloop2l19_43 { + actions = { + forloop2l19_43(); + } + const default_action = forloop2l19_43(); + } + @hidden table tbl_forloop2l18_44 { + actions = { + forloop2l18_44(); + } + const default_action = forloop2l18_44(); + } + @hidden table tbl_forloop2l19_44 { + actions = { + forloop2l19_44(); + } + const default_action = forloop2l19_44(); + } + @hidden table tbl_forloop2l18_45 { + actions = { + forloop2l18_45(); + } + const default_action = forloop2l18_45(); + } + @hidden table tbl_forloop2l19_45 { + actions = { + forloop2l19_45(); + } + const default_action = forloop2l19_45(); + } + @hidden table tbl_forloop2l18_46 { + actions = { + forloop2l18_46(); + } + const default_action = forloop2l18_46(); + } + @hidden table tbl_forloop2l19_46 { + actions = { + forloop2l19_46(); + } + const default_action = forloop2l19_46(); + } + @hidden table tbl_forloop2l18_47 { + actions = { + forloop2l18_47(); + } + const default_action = forloop2l18_47(); + } + @hidden table tbl_forloop2l19_47 { + actions = { + forloop2l19_47(); + } + const default_action = forloop2l19_47(); + } + @hidden table tbl_forloop2l18_48 { + actions = { + forloop2l18_48(); + } + const default_action = forloop2l18_48(); + } + @hidden table tbl_forloop2l19_48 { + actions = { + forloop2l19_48(); + } + const default_action = forloop2l19_48(); + } + @hidden table tbl_forloop2l18_49 { + actions = { + forloop2l18_49(); + } + const default_action = forloop2l18_49(); + } + @hidden table tbl_forloop2l19_49 { + actions = { + forloop2l19_49(); + } + const default_action = forloop2l19_49(); + } + @hidden table tbl_forloop2l18_50 { + actions = { + forloop2l18_50(); + } + const default_action = forloop2l18_50(); + } + @hidden table tbl_forloop2l19_50 { + actions = { + forloop2l19_50(); + } + const default_action = forloop2l19_50(); + } + @hidden table tbl_forloop2l18_51 { + actions = { + forloop2l18_51(); + } + const default_action = forloop2l18_51(); + } + @hidden table tbl_forloop2l19_51 { + actions = { + forloop2l19_51(); + } + const default_action = forloop2l19_51(); + } + @hidden table tbl_forloop2l18_52 { + actions = { + forloop2l18_52(); + } + const default_action = forloop2l18_52(); + } + @hidden table tbl_forloop2l19_52 { + actions = { + forloop2l19_52(); + } + const default_action = forloop2l19_52(); + } + @hidden table tbl_forloop2l18_53 { + actions = { + forloop2l18_53(); + } + const default_action = forloop2l18_53(); + } + @hidden table tbl_forloop2l19_53 { + actions = { + forloop2l19_53(); + } + const default_action = forloop2l19_53(); + } + @hidden table tbl_forloop2l18_54 { + actions = { + forloop2l18_54(); + } + const default_action = forloop2l18_54(); + } + @hidden table tbl_forloop2l19_54 { + actions = { + forloop2l19_54(); + } + const default_action = forloop2l19_54(); + } + @hidden table tbl_forloop2l18_55 { + actions = { + forloop2l18_55(); + } + const default_action = forloop2l18_55(); + } + @hidden table tbl_forloop2l19_55 { + actions = { + forloop2l19_55(); + } + const default_action = forloop2l19_55(); + } + @hidden table tbl_forloop2l18_56 { + actions = { + forloop2l18_56(); + } + const default_action = forloop2l18_56(); + } + @hidden table tbl_forloop2l19_56 { + actions = { + forloop2l19_56(); + } + const default_action = forloop2l19_56(); + } + @hidden table tbl_forloop2l18_57 { + actions = { + forloop2l18_57(); + } + const default_action = forloop2l18_57(); + } + @hidden table tbl_forloop2l19_57 { + actions = { + forloop2l19_57(); + } + const default_action = forloop2l19_57(); + } + @hidden table tbl_forloop2l18_58 { + actions = { + forloop2l18_58(); + } + const default_action = forloop2l18_58(); + } + @hidden table tbl_forloop2l19_58 { + actions = { + forloop2l19_58(); + } + const default_action = forloop2l19_58(); + } + @hidden table tbl_forloop2l18_59 { + actions = { + forloop2l18_59(); + } + const default_action = forloop2l18_59(); + } + @hidden table tbl_forloop2l19_59 { + actions = { + forloop2l19_59(); + } + const default_action = forloop2l19_59(); + } + @hidden table tbl_forloop2l18_60 { + actions = { + forloop2l18_60(); + } + const default_action = forloop2l18_60(); + } + @hidden table tbl_forloop2l19_60 { + actions = { + forloop2l19_60(); + } + const default_action = forloop2l19_60(); + } + @hidden table tbl_forloop2l18_61 { + actions = { + forloop2l18_61(); + } + const default_action = forloop2l18_61(); + } + @hidden table tbl_forloop2l19_61 { + actions = { + forloop2l19_61(); + } + const default_action = forloop2l19_61(); + } + @hidden table tbl_forloop2l22 { + actions = { + forloop2l22(); + } + const default_action = forloop2l22(); + } + @hidden table tbl_forloop2l27 { + actions = { + forloop2l27(); + } + const default_action = forloop2l27(); + } + apply { + tbl_forloop2l14.apply(); + tbl_act.apply(); + if (hdrs.t1.v == 64w0) { + tbl_forloop2l18.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_0.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_0.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_1.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_1.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_2.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_2.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_3.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_3.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_4.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_4.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_5.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_5.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_6.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_6.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_7.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_7.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_8.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_8.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_9.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_9.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_10.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_10.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_11.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_11.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_12.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_12.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_13.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_13.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_14.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_14.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_15.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_15.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_16.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_16.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_17.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_17.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_18.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_18.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_19.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_19.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_20.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_20.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_21.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_21.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_22.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_22.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_23.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_23.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_24.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_24.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_25.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_25.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_26.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_26.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_27.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_27.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_28.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_28.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_29.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_29.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_30.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_30.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_31.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_31.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_32.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_32.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_33.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_33.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_34.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_34.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_35.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_35.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_36.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_36.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_37.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_37.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_38.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_38.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_39.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_39.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_40.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_40.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_41.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_41.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_42.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_42.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_43.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_43.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_44.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_44.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_45.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_45.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_46.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_46.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_47.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_47.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_48.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_48.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_49.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_49.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_50.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_50.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_51.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_51.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_52.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_52.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_53.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_53.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_54.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_54.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_55.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_55.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_56.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_56.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_57.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_57.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_58.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_58.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_59.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_59.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_60.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_60.apply(); + } + if (breakFlag) { + ; + } else { + if (v_0 == 64w0) { + tbl_forloop2l18_61.apply(); + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + tbl_forloop2l19_61.apply(); + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + if (hasReturned) { + ; + } else { + tbl_forloop2l22.apply(); + } + tbl_forloop2l27.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop2.p4 b/testdata/p4_16_samples_outputs/forloop2.p4 new file mode 100644 index 0000000000..8ba8cdd304 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop2.p4 @@ -0,0 +1,31 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<64> v; +} + +struct headers_t { + t1 t1; +} + +bit<64> _popcount(in bit<64> val) { + bit<64> n = 0; + bit<64> v = val; + for (bit<64> popcnti in 1 .. 64w63) { + if (v == 0) { + return n; + } + n = n + 1; + v = v & v - 1; + } + return n; +} +control c(inout headers_t hdrs) { + apply { + hdrs.t1.v = _popcount(hdrs.t1.v); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop2.p4-stderr b/testdata/p4_16_samples_outputs/forloop2.p4-stderr new file mode 100644 index 0000000000..063aefea8a --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop2.p4-stderr @@ -0,0 +1,2 @@ +[--Wwarn=uninitialized_use] warning: retval may be uninitialized +[--Wwarn=uninitialized_use] warning: retval may be uninitialized diff --git a/testdata/p4_16_samples_outputs/forloop3-first.p4 b/testdata/p4_16_samples_outputs/forloop3-first.p4 new file mode 100644 index 0000000000..fba6d88336 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop3-first.p4 @@ -0,0 +1,54 @@ +#include + +control generic(inout M m); +package top(generic c); +extern T foo(in T x); +header t1 { + bit<32> x; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0(bit<8> x, bit<8> y) { + bit<8> idx = 8w255; + for (bit<8> i1 in 8w0 .. x) { + for (bit<8> j in i1 .. y) { + idx = foo>(j); + if (idx == 8w255) { + break; + } + } + } + } + action a1(bit<8> x, bit<8> y) { + bit<8> idx = 8w255; + for (bit<8> i in 8w0 .. x) { + for (bit<8> j in 8w0 .. y) { + idx = foo>(j); + if (idx == 8w255) { + continue; + } + idx = foo>(i); + } + } + } + table test { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + a1(); + @defaultonly NoAction(); + } + default_action = NoAction(); + } + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop3-frontend.p4 b/testdata/p4_16_samples_outputs/forloop3-frontend.p4 new file mode 100644 index 0000000000..a19b7b25c7 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop3-frontend.p4 @@ -0,0 +1,60 @@ +#include + +control generic(inout M m); +package top(generic c); +extern T foo(in T x); +header t1 { + bit<32> x; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.idx") bit<8> idx_0; + @name("c.i1") bit<8> i1_0; + @name("c.j") bit<8> j_0; + @name("c.idx") bit<8> idx_1; + @name("c.i") bit<8> i_0; + @name("c.j") bit<8> j_1; + @noWarn("unused") @name(".NoAction") action NoAction_1() { + } + @name("c.a0") action a0(@name("x") bit<8> x_2, @name("y") bit<8> y) { + for (i1_0 in 8w0 .. x_2) { + for (j_0 in i1_0 .. y) { + idx_0 = foo>(j_0); + if (idx_0 == 8w255) { + break; + } + } + } + } + @name("c.a1") action a1(@name("x") bit<8> x_3, @name("y") bit<8> y_2) { + for (i_0 in 8w0 .. x_3) { + for (j_1 in 8w0 .. y_2) { + idx_1 = foo>(j_1); + if (idx_1 == 8w255) { + continue; + } + foo>(i_0); + } + } + } + @name("c.test") table test_0 { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + a1(); + @defaultonly NoAction_1(); + } + default_action = NoAction_1(); + } + apply { + test_0.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop3-midend.p4 b/testdata/p4_16_samples_outputs/forloop3-midend.p4 new file mode 100644 index 0000000000..a19b7b25c7 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop3-midend.p4 @@ -0,0 +1,60 @@ +#include + +control generic(inout M m); +package top(generic c); +extern T foo(in T x); +header t1 { + bit<32> x; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.idx") bit<8> idx_0; + @name("c.i1") bit<8> i1_0; + @name("c.j") bit<8> j_0; + @name("c.idx") bit<8> idx_1; + @name("c.i") bit<8> i_0; + @name("c.j") bit<8> j_1; + @noWarn("unused") @name(".NoAction") action NoAction_1() { + } + @name("c.a0") action a0(@name("x") bit<8> x_2, @name("y") bit<8> y) { + for (i1_0 in 8w0 .. x_2) { + for (j_0 in i1_0 .. y) { + idx_0 = foo>(j_0); + if (idx_0 == 8w255) { + break; + } + } + } + } + @name("c.a1") action a1(@name("x") bit<8> x_3, @name("y") bit<8> y_2) { + for (i_0 in 8w0 .. x_3) { + for (j_1 in 8w0 .. y_2) { + idx_1 = foo>(j_1); + if (idx_1 == 8w255) { + continue; + } + foo>(i_0); + } + } + } + @name("c.test") table test_0 { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + a1(); + @defaultonly NoAction_1(); + } + default_action = NoAction_1(); + } + apply { + test_0.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop3.p4 b/testdata/p4_16_samples_outputs/forloop3.p4 new file mode 100644 index 0000000000..07038f6cd1 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop3.p4 @@ -0,0 +1,52 @@ +#include + +control generic(inout M m); +package top(generic c); +extern T foo(in T x); +header t1 { + bit<32> x; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0(bit<8> x, bit<8> y) { + bit<8> idx = 255; + for (bit<8> i1 in 0 .. x) { + for (bit<8> j in i1 .. y) { + idx = foo(j); + if (idx == 255) { + break; + } + } + } + } + action a1(bit<8> x, bit<8> y) { + bit<8> idx = 255; + for (bit<8> i in 0 .. x) { + for (bit<8> j in 0 .. y) { + idx = foo(j); + if (idx == 255) { + continue; + } + idx = foo(i); + } + } + } + table test { + key = { + hdrs.t1.x: exact; + } + actions = { + a0; + a1; + } + } + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop3.p4-stderr b/testdata/p4_16_samples_outputs/forloop3.p4-stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/p4_16_samples_outputs/forloop4-first.p4 b/testdata/p4_16_samples_outputs/forloop4-first.p4 new file mode 100644 index 0000000000..ed95975860 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop4-first.p4 @@ -0,0 +1,61 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; +} + +struct headers_t { + t1 t1; +} + +bit<8> foo(in bit<8> aa, in bit<8> bb) { + return aa - bb; +} +control c(inout headers_t hdrs) { + action a0(bit<8> x, bit<8> y) { + for (bit<8> i in 8w1 .. x + y) { + foo(x, y); + } + for (bit<8> i in 8w1 .. x + y) { + foo(x, y + i); + } + for (bit<8> i in 8w1 .. 8w42) { + foo(x, y + i); + } + } + action a1(bit<8> x, bit<8> y) { + for (bit<8> i in 8w1 .. x) { + for (bit<8> j in i .. y) { + foo(x, y + i); + } + } + } + action a2(bit<8> x, bit<8> y) { + bit<8> i = 8w10; + for (bit<8> i in 8w1 .. x) { + foo(x, y + i); + } + for (bit<8> k in i .. x + y) { + foo(i, (i << 1) + x); + } + } + table test { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + a1(); + a2(); + @defaultonly NoAction(); + } + default_action = NoAction(); + } + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop4-frontend.p4 b/testdata/p4_16_samples_outputs/forloop4-frontend.p4 new file mode 100644 index 0000000000..48579cabd2 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop4-frontend.p4 @@ -0,0 +1,68 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.i") bit<8> i_0; + @name("c.i") bit<8> i_1; + @name("c.i") bit<8> i_2; + @name("c.i") bit<8> i_3; + @name("c.j") bit<8> j_0; + @name("c.i") bit<8> i_4; + @name("c.i") bit<8> i_5; + @name("c.k") bit<8> k_0; + @noWarn("unused") @name(".NoAction") action NoAction_1() { + } + @name("c.a0") action a0(@name("x") bit<8> x_3, @name("y") bit<8> y) { + for (i_0 in 8w1 .. x_3 + y) { + ; + } + for (i_1 in 8w1 .. x_3 + y) { + ; + } + for (i_2 in 8w1 .. 8w42) { + ; + } + } + @name("c.a1") action a1(@name("x") bit<8> x_4, @name("y") bit<8> y_3) { + for (i_3 in 8w1 .. x_4) { + for (j_0 in i_3 .. y_3) { + ; + } + } + } + @name("c.a2") action a2(@name("x") bit<8> x_5, @name("y") bit<8> y_4) { + i_4 = 8w10; + for (i_5 in 8w1 .. x_5) { + ; + } + for (k_0 in i_4 .. x_5 + y_4) { + ; + } + } + @name("c.test") table test_0 { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + a1(); + a2(); + @defaultonly NoAction_1(); + } + default_action = NoAction_1(); + } + apply { + test_0.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop4-midend.p4 b/testdata/p4_16_samples_outputs/forloop4-midend.p4 new file mode 100644 index 0000000000..153ebc94a3 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop4-midend.p4 @@ -0,0 +1,62 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.i") bit<8> i_0; + @name("c.i") bit<8> i_1; + @name("c.i") bit<8> i_3; + @name("c.j") bit<8> j_0; + @name("c.i") bit<8> i_5; + @name("c.k") bit<8> k_0; + @noWarn("unused") @name(".NoAction") action NoAction_1() { + } + @name("c.a0") action a0(@name("x") bit<8> x_3, @name("y") bit<8> y) { + for (i_0 in 8w1 .. x_3 + y) { + ; + } + for (i_1 in 8w1 .. x_3 + y) { + ; + } + } + @name("c.a1") action a1(@name("x") bit<8> x_4, @name("y") bit<8> y_3) { + for (i_3 in 8w1 .. x_4) { + for (j_0 in i_3 .. y_3) { + ; + } + } + } + @name("c.a2") action a2(@name("x") bit<8> x_5, @name("y") bit<8> y_4) { + for (i_5 in 8w1 .. x_5) { + ; + } + for (k_0 in 8w10 .. x_5 + y_4) { + ; + } + } + @name("c.test") table test_0 { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + a1(); + a2(); + @defaultonly NoAction_1(); + } + default_action = NoAction_1(); + } + apply { + test_0.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop4.p4 b/testdata/p4_16_samples_outputs/forloop4.p4 new file mode 100644 index 0000000000..be6148d0ce --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop4.p4 @@ -0,0 +1,59 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; +} + +struct headers_t { + t1 t1; +} + +bit<8> foo(in bit<8> aa, in bit<8> bb) { + return aa - bb; +} +control c(inout headers_t hdrs) { + action a0(bit<8> x, bit<8> y) { + for (bit<8> i in 1 .. x + y) { + foo(x, y); + } + for (bit<8> i in 1 .. x + y) { + foo(x, y + i); + } + for (bit<8> i in 8w1 .. 42) { + foo(x, y + i); + } + } + action a1(bit<8> x, bit<8> y) { + for (bit<8> i in 1 .. x) { + for (bit<8> j in i .. y) { + foo(x, y + i); + } + } + } + action a2(bit<8> x, bit<8> y) { + bit<8> i = 10; + for (bit<8> i in 1 .. x) { + foo(x, y + i); + } + for (bit<8> k in i .. x + y) { + foo(i, 2 * i + x); + } + } + table test { + key = { + hdrs.t1.x: exact; + } + actions = { + a0; + a1; + a2; + } + } + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop4.p4-stderr b/testdata/p4_16_samples_outputs/forloop4.p4-stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/p4_16_samples_outputs/forloop5-first.p4 b/testdata/p4_16_samples_outputs/forloop5-first.p4 new file mode 100644 index 0000000000..2db39bf0e1 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop5-first.p4 @@ -0,0 +1,28 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0() { + bit<32> result = 32w0; + for (bit<8> i = 8w0; i < 8w4; i = i + 8w1) { + result = result << 8; + result = result + ((hdrs.t1.x >> (i << 3)) + (hdrs.t1.y >> (i << 3)) & 32w0xff); + } + hdrs.t1.x = result; + } + apply { + a0(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop5-frontend.p4 b/testdata/p4_16_samples_outputs/forloop5-frontend.p4 new file mode 100644 index 0000000000..a9386973c4 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop5-frontend.p4 @@ -0,0 +1,30 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.result") bit<32> result_0; + @name("c.i") bit<8> i_0; + @name("c.a0") action a0() { + result_0 = 32w0; + for (i_0 = 8w0; i_0 < 8w4; i_0 = i_0 + 8w1) { + result_0 = result_0 << 8; + result_0 = result_0 + ((hdrs.t1.x >> (i_0 << 3)) + (hdrs.t1.y >> (i_0 << 3)) & 32w0xff); + } + hdrs.t1.x = result_0; + } + apply { + a0(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop5-midend.p4 b/testdata/p4_16_samples_outputs/forloop5-midend.p4 new file mode 100644 index 0000000000..143a2999eb --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop5-midend.p4 @@ -0,0 +1,29 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.a0") action a0() { + hdrs.t1.x = ((((hdrs.t1.x + hdrs.t1.y & 32w0xff) << 8) + ((hdrs.t1.x >> 8w8) + (hdrs.t1.y >> 8w8) & 32w0xff) << 8) + ((hdrs.t1.x >> 8w16) + (hdrs.t1.y >> 8w16) & 32w0xff) << 8) + ((hdrs.t1.x >> 8w24) + (hdrs.t1.y >> 8w24) & 32w0xff); + } + @hidden table tbl_a0 { + actions = { + a0(); + } + const default_action = a0(); + } + apply { + tbl_a0.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop5.p4 b/testdata/p4_16_samples_outputs/forloop5.p4 new file mode 100644 index 0000000000..af1962365c --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop5.p4 @@ -0,0 +1,28 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0() { + bit<32> result = 0; + for (bit<8> i = 0; i < 4; i = i + 1) { + result = result << 8; + result = result + ((hdrs.t1.x >> 8 * i) + (hdrs.t1.y >> 8 * i) & 0xff); + } + hdrs.t1.x = result; + } + apply { + a0(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop5.p4-stderr b/testdata/p4_16_samples_outputs/forloop5.p4-stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/p4_16_samples_outputs/forloop6-first.p4 b/testdata/p4_16_samples_outputs/forloop6-first.p4 new file mode 100644 index 0000000000..d848578ae5 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop6-first.p4 @@ -0,0 +1,44 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0(bit<8> m) { + bit<32> result = 32w0; + bit<8> mask = m; + for (bit<8> i = 8w0; i < 8w32; i = i + 8w4, mask = mask >> 1) { + if (mask == 8w0) { + break; + } + if (mask[0:0] == 1w0) { + continue; + } + result = result + (hdrs.t1.y >> i & 32w0xf); + } + hdrs.t1.y = result; + } + table test { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + @defaultonly NoAction(); + } + default_action = NoAction(); + } + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop6-frontend.p4 b/testdata/p4_16_samples_outputs/forloop6-frontend.p4 new file mode 100644 index 0000000000..58e3c6eadf --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop6-frontend.p4 @@ -0,0 +1,49 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.result") bit<32> result_0; + @name("c.mask") bit<8> mask_0; + @name("c.i") bit<8> i_0; + @noWarn("unused") @name(".NoAction") action NoAction_1() { + } + @name("c.a0") action a0(@name("m") bit<8> m_1) { + result_0 = 32w0; + mask_0 = m_1; + for (i_0 = 8w0; i_0 < 8w32; i_0 = i_0 + 8w4, mask_0 = mask_0 >> 1) { + if (mask_0 == 8w0) { + break; + } + if (mask_0[0:0] == 1w0) { + continue; + } + result_0 = result_0 + (hdrs.t1.y >> i_0 & 32w0xf); + } + hdrs.t1.y = result_0; + } + @name("c.test") table test_0 { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + @defaultonly NoAction_1(); + } + default_action = NoAction_1(); + } + apply { + test_0.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop6-midend.p4 b/testdata/p4_16_samples_outputs/forloop6-midend.p4 new file mode 100644 index 0000000000..99fe863874 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop6-midend.p4 @@ -0,0 +1,164 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.result") bit<32> result_0; + bool breakFlag; + bool continueFlag; + @noWarn("unused") @name(".NoAction") action NoAction_1() { + } + @name("c.a0") action a0(@name("m") bit<8> m_1) { + result_0 = 32w0; + breakFlag = false; + continueFlag = false; + if (m_1 == 8w0) { + breakFlag = true; + } + if (breakFlag) { + ; + } else if (m_1[0:0] == 1w0) { + continueFlag = true; + } + if (!breakFlag && !continueFlag) { + result_0 = hdrs.t1.y & 32w0xf; + } + if (breakFlag) { + ; + } else { + continueFlag = false; + if (m_1 >> 1 == 8w0) { + breakFlag = true; + } + if (breakFlag) { + ; + } else if (m_1[1:1] == 1w0) { + continueFlag = true; + } + if (!breakFlag && !continueFlag) { + result_0 = result_0 + (hdrs.t1.y >> 8w4 & 32w0xf); + } + if (breakFlag) { + ; + } else { + continueFlag = false; + if (m_1 >> 2 == 8w0) { + breakFlag = true; + } + if (breakFlag) { + ; + } else if (m_1[2:2] == 1w0) { + continueFlag = true; + } + if (!breakFlag && !continueFlag) { + result_0 = result_0 + (hdrs.t1.y >> 8w8 & 32w0xf); + } + if (breakFlag) { + ; + } else { + continueFlag = false; + if (m_1 >> 3 == 8w0) { + breakFlag = true; + } + if (breakFlag) { + ; + } else if (m_1[3:3] == 1w0) { + continueFlag = true; + } + if (!breakFlag && !continueFlag) { + result_0 = result_0 + (hdrs.t1.y >> 8w12 & 32w0xf); + } + if (breakFlag) { + ; + } else { + continueFlag = false; + if (m_1 >> 4 == 8w0) { + breakFlag = true; + } + if (breakFlag) { + ; + } else if (m_1[4:4] == 1w0) { + continueFlag = true; + } + if (!breakFlag && !continueFlag) { + result_0 = result_0 + (hdrs.t1.y >> 8w16 & 32w0xf); + } + if (breakFlag) { + ; + } else { + continueFlag = false; + if (m_1 >> 5 == 8w0) { + breakFlag = true; + } + if (breakFlag) { + ; + } else if (m_1[5:5] == 1w0) { + continueFlag = true; + } + if (!breakFlag && !continueFlag) { + result_0 = result_0 + (hdrs.t1.y >> 8w20 & 32w0xf); + } + if (breakFlag) { + ; + } else { + continueFlag = false; + if (m_1 >> 6 == 8w0) { + breakFlag = true; + } + if (breakFlag) { + ; + } else if (m_1[6:6] == 1w0) { + continueFlag = true; + } + if (!breakFlag && !continueFlag) { + result_0 = result_0 + (hdrs.t1.y >> 8w24 & 32w0xf); + } + if (breakFlag) { + ; + } else { + continueFlag = false; + if (m_1 >> 7 == 8w0) { + breakFlag = true; + } + if (breakFlag) { + ; + } else if (m_1[7:7] == 1w0) { + continueFlag = true; + } + if (!breakFlag && !continueFlag) { + result_0 = result_0 + (hdrs.t1.y >> 8w28 & 32w0xf); + } + } + } + } + } + } + } + } + hdrs.t1.y = result_0; + } + @name("c.test") table test_0 { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + @defaultonly NoAction_1(); + } + default_action = NoAction_1(); + } + apply { + test_0.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop6.p4 b/testdata/p4_16_samples_outputs/forloop6.p4 new file mode 100644 index 0000000000..58993b03df --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop6.p4 @@ -0,0 +1,42 @@ +#include + +control generic(inout M m); +package top(generic c); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0(bit<8> m) { + bit<32> result = 0; + bit<8> mask = m; + for (bit<8> i = 0; i < 32; i = i + 4, mask = mask >> 1) { + if (mask == 0) { + break; + } + if (mask[0:0] == 0) { + continue; + } + result = result + (hdrs.t1.y >> i & 0xf); + } + hdrs.t1.y = result; + } + table test { + key = { + hdrs.t1.x: exact; + } + actions = { + a0; + } + } + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop6.p4-stderr b/testdata/p4_16_samples_outputs/forloop6.p4-stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/p4_16_samples_outputs/forloop7-first.p4 b/testdata/p4_16_samples_outputs/forloop7-first.p4 new file mode 100644 index 0000000000..1b6d038aca --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop7-first.p4 @@ -0,0 +1,45 @@ +#include + +control generic(inout M m); +package top(generic c); +extern bool fn(in bit<16> a, in bit<16> b); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0(bit<8> m) { + for (bit<16> a in 16w1 .. 16w2) { + fn(a, 16w0); + for (bit<16> b in 16w1 .. 16w2) { + if (fn(a, b)) { + continue; + } + return; + } + fn(a, 16w3); + fn(a, 16w4); + } + fn(16w3, 16w3); + } + table test { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + @defaultonly NoAction(); + } + default_action = NoAction(); + } + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop7-frontend.p4 b/testdata/p4_16_samples_outputs/forloop7-frontend.p4 new file mode 100644 index 0000000000..61f87dcfd0 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop7-frontend.p4 @@ -0,0 +1,65 @@ +#include + +control generic(inout M m); +package top(generic c); +extern bool fn(in bit<16> a, in bit<16> b); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.a") bit<16> a_0; + @name("c.b") bit<16> b_0; + @name("c.tmp") bool tmp; + @name("c.hasReturned") bool hasReturned; + @noWarn("unused") @name(".NoAction") action NoAction_1() { + } + @name("c.a0") action a0(@name("m") bit<8> m_1) { + hasReturned = false; + for (a_0 in 16w1 .. 16w2) { + fn(a_0, 16w0); + for (b_0 in 16w1 .. 16w2) { + tmp = fn(a_0, b_0); + if (tmp) { + continue; + } + hasReturned = true; + break; + } + if (hasReturned) { + break; + } + if (hasReturned) { + ; + } else { + fn(a_0, 16w3); + fn(a_0, 16w4); + } + } + if (hasReturned) { + ; + } else { + fn(16w3, 16w3); + } + } + @name("c.test") table test_0 { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + @defaultonly NoAction_1(); + } + default_action = NoAction_1(); + } + apply { + test_0.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop7-midend.p4 b/testdata/p4_16_samples_outputs/forloop7-midend.p4 new file mode 100644 index 0000000000..6693e4896e --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop7-midend.p4 @@ -0,0 +1,147 @@ +#include + +control generic(inout M m); +package top(generic c); +extern bool fn(in bit<16> a, in bit<16> b); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + @name("c.tmp") bool tmp; + @name("c.hasReturned") bool hasReturned; + bool breakFlag; + bool breakFlag_0; + bool continueFlag; + bool breakFlag_1; + bool continueFlag_0; + @noWarn("unused") @name(".NoAction") action NoAction_1() { + } + @name("c.a0") action a0(@name("m") bit<8> m_1) { + hasReturned = false; + breakFlag = false; + fn(16w1, 16w0); + breakFlag_0 = false; + continueFlag = false; + tmp = fn(16w1, 16w1); + if (tmp) { + continueFlag = true; + } + if (continueFlag) { + ; + } else { + hasReturned = true; + } + if (continueFlag) { + ; + } else { + breakFlag_0 = true; + } + if (breakFlag_0) { + ; + } else { + continueFlag = false; + tmp = fn(16w1, 16w2); + if (tmp) { + continueFlag = true; + } + if (continueFlag) { + ; + } else { + hasReturned = true; + } + if (continueFlag) { + ; + } else { + breakFlag_0 = true; + } + } + if (hasReturned) { + breakFlag = true; + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + fn(16w1, 16w3); + fn(16w1, 16w4); + } + if (breakFlag) { + ; + } else { + fn(16w2, 16w0); + breakFlag_1 = false; + continueFlag_0 = false; + tmp = fn(16w2, 16w1); + if (tmp) { + continueFlag_0 = true; + } + if (continueFlag_0) { + ; + } else { + hasReturned = true; + } + if (continueFlag_0) { + ; + } else { + breakFlag_1 = true; + } + if (breakFlag_1) { + ; + } else { + continueFlag_0 = false; + tmp = fn(16w2, 16w2); + if (tmp) { + continueFlag_0 = true; + } + if (continueFlag_0) { + ; + } else { + hasReturned = true; + } + if (continueFlag_0) { + ; + } else { + breakFlag_1 = true; + } + } + if (hasReturned) { + breakFlag = true; + } + if (breakFlag) { + ; + } else if (hasReturned) { + ; + } else { + fn(16w2, 16w3); + fn(16w2, 16w4); + } + } + if (hasReturned) { + ; + } else { + fn(16w3, 16w3); + } + } + @name("c.test") table test_0 { + key = { + hdrs.t1.x: exact @name("hdrs.t1.x"); + } + actions = { + a0(); + @defaultonly NoAction_1(); + } + default_action = NoAction_1(); + } + apply { + test_0.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop7.p4 b/testdata/p4_16_samples_outputs/forloop7.p4 new file mode 100644 index 0000000000..d6c4e1b0d6 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop7.p4 @@ -0,0 +1,43 @@ +#include + +control generic(inout M m); +package top(generic c); +extern bool fn(in bit<16> a, in bit<16> b); +header t1 { + bit<32> x; + bit<32> y; +} + +struct headers_t { + t1 t1; +} + +control c(inout headers_t hdrs) { + action a0(bit<8> m) { + for (bit<16> a in 1 .. 2) { + fn(a, 0); + for (bit<16> b in 1 .. 2) { + if (fn(a, b)) { + continue; + } + return; + } + fn(a, 3); + fn(a, 4); + } + fn(3, 3); + } + table test { + key = { + hdrs.t1.x: exact; + } + actions = { + a0; + } + } + apply { + test.apply(); + } +} + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/forloop7.p4-stderr b/testdata/p4_16_samples_outputs/forloop7.p4-stderr new file mode 100644 index 0000000000..597d374954 --- /dev/null +++ b/testdata/p4_16_samples_outputs/forloop7.p4-stderr @@ -0,0 +1,3 @@ +forloop7.p4(17): [--Wwarn=unused] warning: 'm' is unused + action a0(bit<8> m) { + ^ diff --git a/testdata/p4_16_samples_outputs/gauntlet_exit_after_valid-bmv2-midend.p4 b/testdata/p4_16_samples_outputs/gauntlet_exit_after_valid-bmv2-midend.p4 index 3f536b6780..7259cbf114 100644 --- a/testdata/p4_16_samples_outputs/gauntlet_exit_after_valid-bmv2-midend.p4 +++ b/testdata/p4_16_samples_outputs/gauntlet_exit_after_valid-bmv2-midend.p4 @@ -29,19 +29,8 @@ parser p(packet_in pkt, out Headers hdr, inout Meta m, inout standard_metadata_t } control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { - bool hasExited; @hidden action gauntlet_exit_after_validbmv2l36() { h.eth_hdr.dst_addr = h.h.a; - hasExited = true; - } - @hidden action act() { - hasExited = false; - } - @hidden table tbl_act { - actions = { - act(); - } - const default_action = act(); } @hidden table tbl_gauntlet_exit_after_validbmv2l36 { actions = { @@ -50,7 +39,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { const default_action = gauntlet_exit_after_validbmv2l36(); } apply { - tbl_act.apply(); if (h.h.isValid()) { tbl_gauntlet_exit_after_validbmv2l36.apply(); } diff --git a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_1-bmv2-midend.p4 b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_1-bmv2-midend.p4 index e61eb2d761..62ddea4266 100644 --- a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_1-bmv2-midend.p4 +++ b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_1-bmv2-midend.p4 @@ -23,7 +23,6 @@ parser p(packet_in pkt, out Headers hdr, inout Meta m, inout standard_metadata_t } control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { - bool hasExited; @name("ingress.hasReturned") bool hasReturned; bit<32> key_0; @noWarn("unused") @name(".NoAction") action NoAction_1() { @@ -32,7 +31,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { } @name("ingress.do_action") action do_action() { h.eth_hdr.eth_type = 16w1; - hasExited = true; } @name("ingress.simple_table") table simple_table_0 { key = { @@ -48,7 +46,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { hasReturned = true; } @hidden action gauntlet_exit_combination_1bmv2l39() { - hasExited = false; hasReturned = false; key_0 = 32w1; } diff --git a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_10-bmv2-midend.p4 b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_10-bmv2-midend.p4 index 19703eef9f..48be044ecf 100644 --- a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_10-bmv2-midend.p4 +++ b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_10-bmv2-midend.p4 @@ -23,13 +23,11 @@ parser p(packet_in pkt, out Headers hdr, inout Meta m, inout standard_metadata_t } control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { - bool hasExited; bit<64> key_0; @noWarn("unused") @name(".NoAction") action NoAction_1() { } @name("ingress.exit_action") action exit_action() { h.eth_hdr.src_addr = 48w2; - hasExited = true; } @name("ingress.simple_table") table simple_table_0 { key = { @@ -42,7 +40,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { default_action = NoAction_1(); } @hidden action gauntlet_exit_combination_10bmv2l34() { - hasExited = false; key_0 = 64w100; } @hidden table tbl_gauntlet_exit_combination_10bmv2l34 { diff --git a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_16-bmv2-midend.p4 b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_16-bmv2-midend.p4 index 20188f1034..c0c0b9a772 100644 --- a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_16-bmv2-midend.p4 +++ b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_16-bmv2-midend.p4 @@ -23,7 +23,6 @@ parser p(packet_in pkt, out Headers hdr, inout Meta m, inout standard_metadata_t } control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { - bool hasExited; @name("ingress.hasReturned") bool hasReturned; bit<8> key_0; @noWarn("unused") @name(".NoAction") action NoAction_1() { @@ -45,13 +44,9 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { hasReturned = true; } @hidden action gauntlet_exit_combination_16bmv2l32() { - hasExited = false; hasReturned = false; key_0 = 8w255; } - @hidden action gauntlet_exit_combination_16bmv2l48() { - hasExited = true; - } @hidden table tbl_gauntlet_exit_combination_16bmv2l32 { actions = { gauntlet_exit_combination_16bmv2l32(); @@ -64,12 +59,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { } const default_action = gauntlet_exit_combination_16bmv2l43(); } - @hidden table tbl_gauntlet_exit_combination_16bmv2l48 { - actions = { - gauntlet_exit_combination_16bmv2l48(); - } - const default_action = gauntlet_exit_combination_16bmv2l48(); - } apply { tbl_gauntlet_exit_combination_16bmv2l32.apply(); switch (simple_table_0.apply().action_run) { @@ -79,11 +68,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { default: { } } - if (hasReturned) { - ; - } else { - tbl_gauntlet_exit_combination_16bmv2l48.apply(); - } } } diff --git a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_17-bmv2-midend.p4 b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_17-bmv2-midend.p4 index a615bf0ec8..5abdd53556 100644 --- a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_17-bmv2-midend.p4 +++ b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_17-bmv2-midend.p4 @@ -23,7 +23,6 @@ parser p(packet_in pkt, out Headers hdr, inout Meta m, inout standard_metadata_t } control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { - bool hasExited; @name("ingress.hasReturned") bool hasReturned; bit<48> key_0; bit<48> key_1; @@ -63,13 +62,9 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { key_1 = 48w1; } @hidden action gauntlet_exit_combination_17bmv2l30() { - hasExited = false; hasReturned = false; key_0 = 48w1; } - @hidden action gauntlet_exit_combination_17bmv2l55() { - hasExited = true; - } @hidden table tbl_gauntlet_exit_combination_17bmv2l30 { actions = { gauntlet_exit_combination_17bmv2l30(); @@ -88,12 +83,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { } const default_action = gauntlet_exit_combination_17bmv2l49(); } - @hidden table tbl_gauntlet_exit_combination_17bmv2l55 { - actions = { - gauntlet_exit_combination_17bmv2l55(); - } - const default_action = gauntlet_exit_combination_17bmv2l55(); - } apply { tbl_gauntlet_exit_combination_17bmv2l30.apply(); switch (simple_table.apply().action_run) { @@ -110,11 +99,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { default: { } } - if (hasReturned) { - ; - } else { - tbl_gauntlet_exit_combination_17bmv2l55.apply(); - } } } diff --git a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_18-bmv2-midend.p4 b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_18-bmv2-midend.p4 index 49996ece8e..f88508753f 100644 --- a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_18-bmv2-midend.p4 +++ b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_18-bmv2-midend.p4 @@ -23,18 +23,7 @@ parser p(packet_in pkt, out Headers hdr, inout Meta m, inout standard_metadata_t } control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { - bool hasExited; @name("ingress.simple_action") action simple_action() { - hasExited = true; - } - @hidden action act() { - hasExited = false; - } - @hidden table tbl_act { - actions = { - act(); - } - const default_action = act(); } @hidden table tbl_simple_action { actions = { @@ -43,7 +32,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { const default_action = simple_action(); } apply { - tbl_act.apply(); tbl_simple_action.apply(); } } diff --git a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_9-bmv2-midend.p4 b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_9-bmv2-midend.p4 index 2af0635c94..169ae8d770 100644 --- a/testdata/p4_16_samples_outputs/gauntlet_exit_combination_9-bmv2-midend.p4 +++ b/testdata/p4_16_samples_outputs/gauntlet_exit_combination_9-bmv2-midend.p4 @@ -23,7 +23,6 @@ parser p(packet_in pkt, out Headers hdr, inout Meta m, inout standard_metadata_t } control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { - bool hasExited; @name("ingress.hasReturned") bool hasReturned; bit<48> key_0; @noWarn("unused") @name(".NoAction") action NoAction_1() { @@ -45,13 +44,11 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { hasReturned = true; } @hidden action gauntlet_exit_combination_9bmv2l35() { - hasExited = false; hasReturned = false; key_0 = 48w1; } @hidden action gauntlet_exit_combination_9bmv2l51() { h.eth_hdr.eth_type = 16w2; - hasExited = true; } @hidden table tbl_gauntlet_exit_combination_9bmv2l35 { actions = { diff --git a/testdata/p4_16_samples_outputs/invalid-hdr-warnings3-bmv2-midend.p4 b/testdata/p4_16_samples_outputs/invalid-hdr-warnings3-bmv2-midend.p4 index a4959d3c7f..0c9bf53935 100644 --- a/testdata/p4_16_samples_outputs/invalid-hdr-warnings3-bmv2-midend.p4 +++ b/testdata/p4_16_samples_outputs/invalid-hdr-warnings3-bmv2-midend.p4 @@ -24,14 +24,13 @@ parser ParserI(packet_in pkt, out H hdr, inout M meta, inout standard_metadata_t control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) { @name("IngressI.h1") Header h1_0; @name("IngressI.h2") Header h2_0; - bit<32> switch_0_key; @hidden action switch_0_case() { } @hidden action switch_0_case_0() { } @hidden table switch_0_table { key = { - switch_0_key: exact; + hdr.h1.data: exact; } actions = { switch_0_case(); @@ -42,14 +41,13 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) { const 32w0 : switch_0_case(); } } - bit<32> switch_1_key; @hidden action switch_1_case() { } @hidden action switch_1_case_0() { } @hidden table switch_1_table { key = { - switch_1_key: exact; + h2_0.data: exact; } actions = { switch_1_case(); @@ -68,9 +66,6 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) { h1_0.setValid(); h2_0.setInvalid(); } - @hidden action invalidhdrwarnings3bmv2l33() { - switch_0_key = hdr.h1.data; - } @hidden action invalidhdrwarnings3bmv2l24() { h1_0.setInvalid(); h2_0.setInvalid(); @@ -86,9 +81,6 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) { h1_0.setInvalid(); h2_0.setInvalid(); } - @hidden action invalidhdrwarnings3bmv2l42() { - switch_1_key = h2_0.data; - } @hidden action invalidhdrwarnings3bmv2l40() { hdr.h1.data = h2_0.data; } @@ -101,12 +93,6 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) { } const default_action = invalidhdrwarnings3bmv2l24(); } - @hidden table tbl_invalidhdrwarnings3bmv2l33 { - actions = { - invalidhdrwarnings3bmv2l33(); - } - const default_action = invalidhdrwarnings3bmv2l33(); - } @hidden table tbl_invalidhdrwarnings3bmv2l35 { actions = { invalidhdrwarnings3bmv2l35(); @@ -125,12 +111,6 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) { } const default_action = invalidhdrwarnings3bmv2l40(); } - @hidden table tbl_invalidhdrwarnings3bmv2l42 { - actions = { - invalidhdrwarnings3bmv2l42(); - } - const default_action = invalidhdrwarnings3bmv2l42(); - } @hidden table tbl_invalidhdrwarnings3bmv2l44 { actions = { invalidhdrwarnings3bmv2l44(); @@ -151,7 +131,6 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) { } apply { tbl_invalidhdrwarnings3bmv2l24.apply(); - tbl_invalidhdrwarnings3bmv2l33.apply(); switch (switch_0_table.apply().action_run) { switch_0_case: { tbl_invalidhdrwarnings3bmv2l35.apply(); @@ -161,7 +140,6 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) { } } tbl_invalidhdrwarnings3bmv2l40.apply(); - tbl_invalidhdrwarnings3bmv2l42.apply(); switch (switch_1_table.apply().action_run) { switch_1_case: { tbl_invalidhdrwarnings3bmv2l44.apply(); diff --git a/testdata/p4_16_samples_outputs/issue1386-midend.p4 b/testdata/p4_16_samples_outputs/issue1386-midend.p4 index 7c85553aa1..77de9883f2 100644 --- a/testdata/p4_16_samples_outputs/issue1386-midend.p4 +++ b/testdata/p4_16_samples_outputs/issue1386-midend.p4 @@ -42,28 +42,9 @@ control deparser(packet_out b, in Headers h) { } control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { - @name("ingress.c.hasReturned") bool c_hasReturned; - @hidden action issue1386l12() { - c_hasReturned = true; - } - @hidden action act() { - c_hasReturned = false; - } @hidden action arithinlineskeleton51() { sm.egress_spec = 9w0; } - @hidden table tbl_act { - actions = { - act(); - } - const default_action = act(); - } - @hidden table tbl_issue1386l12 { - actions = { - issue1386l12(); - } - const default_action = issue1386l12(); - } @hidden table tbl_arithinlineskeleton51 { actions = { arithinlineskeleton51(); @@ -71,12 +52,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { const default_action = arithinlineskeleton51(); } apply { - tbl_act.apply(); - if (h.h.isValid()) { - ; - } else { - tbl_issue1386l12.apply(); - } tbl_arithinlineskeleton51.apply(); } } diff --git a/testdata/p4_16_samples_outputs/issue2225-bmv2-midend.p4 b/testdata/p4_16_samples_outputs/issue2225-bmv2-midend.p4 index 0a052b5e42..ac4a553d9f 100644 --- a/testdata/p4_16_samples_outputs/issue2225-bmv2-midend.p4 +++ b/testdata/p4_16_samples_outputs/issue2225-bmv2-midend.p4 @@ -23,19 +23,8 @@ parser p(packet_in pkt, out Headers hdr, inout Meta m, inout standard_metadata_t } control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { - bool hasExited; @name("ingress.do_action") action do_action() { h.eth_hdr.eth_type = 16w3; - hasExited = true; - } - @hidden action act() { - hasExited = false; - } - @hidden table tbl_act { - actions = { - act(); - } - const default_action = act(); } @hidden table tbl_do_action { actions = { @@ -44,7 +33,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { const default_action = do_action(); } apply { - tbl_act.apply(); tbl_do_action.apply(); } } diff --git a/testdata/p4_16_samples_outputs/issue2359-midend.p4 b/testdata/p4_16_samples_outputs/issue2359-midend.p4 index fa1659cc3c..f3e3597482 100644 --- a/testdata/p4_16_samples_outputs/issue2359-midend.p4 +++ b/testdata/p4_16_samples_outputs/issue2359-midend.p4 @@ -23,27 +23,12 @@ parser p(packet_in pkt, out Headers hdr, inout Meta m, inout standard_metadata_t } control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { - bool hasExited; @name("ingress.hasReturned") bool hasReturned; @name("ingress.do_action") action do_action() { hasReturned = false; if (h.eth_hdr.eth_type == 16w1) { hasReturned = true; } - if (hasReturned) { - ; - } else { - hasExited = true; - } - } - @hidden action act() { - hasExited = false; - } - @hidden table tbl_act { - actions = { - act(); - } - const default_action = act(); } @hidden table tbl_do_action { actions = { @@ -52,7 +37,6 @@ control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { const default_action = do_action(); } apply { - tbl_act.apply(); tbl_do_action.apply(); } } diff --git a/testdata/p4_16_samples_outputs/issue2544_shadowing2.p4-stderr b/testdata/p4_16_samples_outputs/issue2544_shadowing2.p4-stderr index fd50260d0f..6098afe455 100644 --- a/testdata/p4_16_samples_outputs/issue2544_shadowing2.p4-stderr +++ b/testdata/p4_16_samples_outputs/issue2544_shadowing2.p4-stderr @@ -1,6 +1,6 @@ issue2544_shadowing2.p4(28): [--Wwarn=shadow] warning: 'foo' shadows 'foo' bit<8> foo = foo; - ^^^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^^^ issue2544_shadowing2.p4(26) bit<8> foo = 4; - ^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^ diff --git a/testdata/p4_16_samples_outputs/issue3374-midend.p4 b/testdata/p4_16_samples_outputs/issue3374-midend.p4 index 8ab98a7b9b..56bae30309 100644 --- a/testdata/p4_16_samples_outputs/issue3374-midend.p4 +++ b/testdata/p4_16_samples_outputs/issue3374-midend.p4 @@ -120,16 +120,16 @@ control ingressImpl(inout headers_t hdrs, inout main_metadata_t meta, inout stan const default_action = execute_1(); size = 1000000; } - bit<12> switch_0_key; @hidden action switch_0_case() { } @hidden action switch_0_case_0() { } @hidden action switch_0_case_1() { } + bit<12> key_1; @hidden table switch_0_table { key = { - switch_0_key: exact; + key_1: exact; } actions = { switch_0_case(); @@ -143,13 +143,13 @@ control ingressImpl(inout headers_t hdrs, inout main_metadata_t meta, inout stan } } @hidden action issue3374l126() { - switch_0_key = hdrs.vlan_tag[2w0].vid; + key_1 = hdrs.vlan_tag[2w0].vid; } @hidden action issue3374l126_0() { - switch_0_key = hdrs.vlan_tag[2w1].vid; + key_1 = hdrs.vlan_tag[2w1].vid; } @hidden action issue3374l126_1() { - switch_0_key = hsVar; + key_1 = hsVar; } @hidden action issue3374l126_2() { hsiVar = meta.depth; diff --git a/testdata/p4_16_samples_outputs/issue3650-midend.p4 b/testdata/p4_16_samples_outputs/issue3650-midend.p4 index dd47d75ef2..91714106d6 100644 --- a/testdata/p4_16_samples_outputs/issue3650-midend.p4 +++ b/testdata/p4_16_samples_outputs/issue3650-midend.p4 @@ -21,14 +21,13 @@ parser MyParser(packet_in packet, out header_t hdr, inout metadata meta, inout s } control MyIngress(inout header_t hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { - bit<8> switch_0_key; @hidden action switch_0_case() { } @hidden action switch_0_case_0() { } @hidden table switch_0_table { key = { - switch_0_key: exact; + hdr.payload.x: exact; } actions = { switch_0_case(); @@ -39,14 +38,13 @@ control MyIngress(inout header_t hdr, inout metadata meta, inout standard_metada const 8w1 : switch_0_case(); } } - bit<8> switch_1_key; @hidden action switch_1_case() { } @hidden action switch_1_case_0() { } @hidden table switch_1_table { key = { - switch_1_key: exact; + hdr.payload.x: exact; } actions = { switch_1_case(); @@ -57,7 +55,6 @@ control MyIngress(inout header_t hdr, inout metadata meta, inout standard_metada const 8w1 : switch_1_case(); } } - bit<8> switch_2_key; @hidden action switch_2_case() { } @hidden action switch_2_case_0() { @@ -66,7 +63,7 @@ control MyIngress(inout header_t hdr, inout metadata meta, inout standard_metada } @hidden table switch_2_table { key = { - switch_2_key: exact; + hdr.payload.x: exact; } actions = { switch_2_case(); @@ -79,38 +76,9 @@ control MyIngress(inout header_t hdr, inout metadata meta, inout standard_metada const 8w0 : switch_2_case_0(); } } - @hidden action issue3650l24() { - switch_0_key = hdr.payload.x; - } - @hidden action issue3650l24_0() { - switch_1_key = hdr.payload.x; - } - @hidden action issue3650l35() { - switch_2_key = hdr.payload.x; - } - @hidden table tbl_issue3650l35 { - actions = { - issue3650l35(); - } - const default_action = issue3650l35(); - } - @hidden table tbl_issue3650l24 { - actions = { - issue3650l24(); - } - const default_action = issue3650l24(); - } - @hidden table tbl_issue3650l24_0 { - actions = { - issue3650l24_0(); - } - const default_action = issue3650l24_0(); - } apply { - tbl_issue3650l35.apply(); switch (switch_2_table.apply().action_run) { switch_2_case: { - tbl_issue3650l24.apply(); switch (switch_0_table.apply().action_run) { switch_0_case: { } @@ -119,7 +87,6 @@ control MyIngress(inout header_t hdr, inout metadata meta, inout standard_metada } } switch_2_case_0: { - tbl_issue3650l24_0.apply(); switch (switch_1_table.apply().action_run) { switch_1_case: { } diff --git a/testdata/p4_16_samples_outputs/issue3702-bmv2-midend.p4 b/testdata/p4_16_samples_outputs/issue3702-bmv2-midend.p4 index bd059a2515..810a620fcc 100644 --- a/testdata/p4_16_samples_outputs/issue3702-bmv2-midend.p4 +++ b/testdata/p4_16_samples_outputs/issue3702-bmv2-midend.p4 @@ -66,7 +66,7 @@ parser v1model_parser(packet_in pkt, out headers_t hdrs, inout local_metadata_t ipv4_0.header_checksum = tmp[79:64]; ipv4_0.src_addr = tmp[63:32]; ipv4_0.dst_addr = tmp[31:0]; - pkt.extract(hdrs.ip, (bit<32>)tmp[155:152] << 2 + 3); + pkt.extract(hdrs.ip, (bit<32>)tmp[155:152] << 5); transition accept; } } diff --git a/testdata/p4_16_samples_outputs/issue4656_const_fold_generic_switch_label_expr-midend.p4 b/testdata/p4_16_samples_outputs/issue4656_const_fold_generic_switch_label_expr-midend.p4 index 451fc73845..658855c64b 100644 --- a/testdata/p4_16_samples_outputs/issue4656_const_fold_generic_switch_label_expr-midend.p4 +++ b/testdata/p4_16_samples_outputs/issue4656_const_fold_generic_switch_label_expr-midend.p4 @@ -19,7 +19,6 @@ control c() { } default_action = NoAction_1(); } - bit<8> switch_0_key; @hidden action switch_0_case() { } @hidden action switch_0_case_0() { @@ -28,7 +27,7 @@ control c() { } @hidden table switch_0_table { key = { - switch_0_key: exact; + tmp: exact; } actions = { switch_0_case(); @@ -47,9 +46,6 @@ control c() { @hidden action issue4656_const_fold_generic_switch_label_expr15() { bar(); } - @hidden action issue4656_const_fold_generic_switch_label_expr13() { - switch_0_key = tmp; - } @hidden action act() { tmp = baz(); } @@ -59,12 +55,6 @@ control c() { } const default_action = act(); } - @hidden table tbl_issue4656_const_fold_generic_switch_label_expr13 { - actions = { - issue4656_const_fold_generic_switch_label_expr13(); - } - const default_action = issue4656_const_fold_generic_switch_label_expr13(); - } @hidden table tbl_issue4656_const_fold_generic_switch_label_expr14 { actions = { issue4656_const_fold_generic_switch_label_expr14(); @@ -79,7 +69,6 @@ control c() { } apply { tbl_act.apply(); - tbl_issue4656_const_fold_generic_switch_label_expr13.apply(); switch (switch_0_table.apply().action_run) { switch_0_case: { tbl_issue4656_const_fold_generic_switch_label_expr14.apply(); diff --git a/testdata/p4_16_samples_outputs/issue561-midend.p4 b/testdata/p4_16_samples_outputs/issue561-midend.p4 index 00f1fe4721..581ea53c5a 100644 --- a/testdata/p4_16_samples_outputs/issue561-midend.p4 +++ b/testdata/p4_16_samples_outputs/issue561-midend.p4 @@ -30,11 +30,9 @@ control c(out bit<32> x) { u_0_h1.setValid(); u_0_h1.f = 32w0; u_0_h2.setInvalid(); - x = x; u_0_h2.setValid(); u_0_h2.g = 32w0; u_0_h1.setInvalid(); - x = x; u2_0[0].h1.setValid(); u2_0[0].h2.setInvalid(); u2_0[0].h1.setValid(); diff --git a/testdata/p4_16_samples_outputs/omec/up4-midend.p4 b/testdata/p4_16_samples_outputs/omec/up4-midend.p4 index 63025ecc2c..05b15083d4 100644 --- a/testdata/p4_16_samples_outputs/omec/up4-midend.p4 +++ b/testdata/p4_16_samples_outputs/omec/up4-midend.p4 @@ -952,15 +952,12 @@ control PreQosPipe(inout parsed_headers_t hdr, inout local_metadata_t local_meta } control PostQosPipe(inout parsed_headers_t hdr, inout local_metadata_t local_meta, inout standard_metadata_t std_meta) { - bool hasExited_0; @name("PostQosPipe.post_qos_counter") counter>(32w1024, CounterType.packets_and_bytes) post_qos_counter_0; @hidden action up4l754() { hdr.packet_in.setValid(); hdr.packet_in.ingress_port = local_meta.preserved_ingress_port; - hasExited_0 = true; } @hidden action up4l752() { - hasExited_0 = false; post_qos_counter_0.count(local_meta.ctr_idx); } @hidden table tbl_up4l752 { diff --git a/testdata/p4_16_samples_outputs/pins/pins_fabric.p4-stderr b/testdata/p4_16_samples_outputs/pins/pins_fabric.p4-stderr index a08ea0f5a3..9483c7c584 100644 --- a/testdata/p4_16_samples_outputs/pins/pins_fabric.p4-stderr +++ b/testdata/p4_16_samples_outputs/pins/pins_fabric.p4-stderr @@ -1,6 +1,6 @@ pins_fabric.p4(645): [--Wwarn=shadow] warning: 'ttl' shadows 'control ttl' bit<8> ttl = 0; - ^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^ pins_fabric.p4(558) control ttl(inout headers_t headers, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { ^^^ diff --git a/testdata/p4_16_samples_outputs/pins/pins_middleblock.p4-stderr b/testdata/p4_16_samples_outputs/pins/pins_middleblock.p4-stderr index 99aea572d1..49c4e8c20d 100644 --- a/testdata/p4_16_samples_outputs/pins/pins_middleblock.p4-stderr +++ b/testdata/p4_16_samples_outputs/pins/pins_middleblock.p4-stderr @@ -1,6 +1,6 @@ pins_middleblock.p4(586): [--Wwarn=shadow] warning: 'ttl' shadows 'control ttl' bit<8> ttl = 0; - ^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^ pins_middleblock.p4(552) control ttl(inout headers_t headers, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { ^^^ diff --git a/testdata/p4_16_samples_outputs/pins/pins_wbb.p4-stderr b/testdata/p4_16_samples_outputs/pins/pins_wbb.p4-stderr index f4dc9db535..804ed768c6 100644 --- a/testdata/p4_16_samples_outputs/pins/pins_wbb.p4-stderr +++ b/testdata/p4_16_samples_outputs/pins/pins_wbb.p4-stderr @@ -1,6 +1,6 @@ pins_wbb.p4(545): [--Wwarn=shadow] warning: 'ttl' shadows 'control ttl' bit<8> ttl = 0; - ^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^ pins_wbb.p4(514) control ttl(inout headers_t headers, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { ^^^ diff --git a/testdata/p4_16_samples_outputs/pna-example-varIndex-2-midend.p4 b/testdata/p4_16_samples_outputs/pna-example-varIndex-2-midend.p4 index 64d3af5e98..d57dbfc473 100644 --- a/testdata/p4_16_samples_outputs/pna-example-varIndex-2-midend.p4 +++ b/testdata/p4_16_samples_outputs/pna-example-varIndex-2-midend.p4 @@ -83,16 +83,16 @@ control MainControlImpl(inout headers_t hdrs, inout main_metadata_t meta, in pna const default_action = execute_3(); size = 1000000; } - bit<12> switch_0_key; @hidden action switch_0_case() { } @hidden action switch_0_case_0() { } @hidden action switch_0_case_1() { } + bit<12> key_1; @hidden table switch_0_table { key = { - switch_0_key: exact; + key_1: exact; } actions = { switch_0_case(); @@ -106,13 +106,13 @@ control MainControlImpl(inout headers_t hdrs, inout main_metadata_t meta, in pna } } @hidden action pnaexamplevarIndex2l125() { - switch_0_key = hdrs.vlan_tag[2w0].vid; + key_1 = hdrs.vlan_tag[2w0].vid; } @hidden action pnaexamplevarIndex2l125_0() { - switch_0_key = hdrs.vlan_tag[2w1].vid; + key_1 = hdrs.vlan_tag[2w1].vid; } @hidden action pnaexamplevarIndex2l125_1() { - switch_0_key = hsVar; + key_1 = hsVar; } @hidden action pnaexamplevarIndex2l125_2() { hsiVar = meta.depth; diff --git a/testdata/p4_16_samples_outputs/psa-example-parser-checksum-midend.p4 b/testdata/p4_16_samples_outputs/psa-example-parser-checksum-midend.p4 index 42ef17d3cf..d086c76399 100644 --- a/testdata/p4_16_samples_outputs/psa-example-parser-checksum-midend.p4 +++ b/testdata/p4_16_samples_outputs/psa-example-parser-checksum-midend.p4 @@ -96,7 +96,6 @@ parser IngressParserImpl(packet_in buffer, out headers hdr, inout metadata user_ } control ingress(inout headers hdr, inout metadata user_meta, in psa_ingress_input_metadata_t istd, inout psa_ingress_output_metadata_t ostd) { - bool hasExited; @noWarn("unused") @name(".ingress_drop") action ingress_drop_0() { ostd.drop = true; } @@ -124,36 +123,16 @@ control ingress(inout headers hdr, inout metadata user_meta, in psa_ingress_inpu } psa_direct_counter = parser_error_counts_0; } - @hidden action psaexampleparserchecksum185() { - hasExited = true; - } - @hidden action act() { - hasExited = false; - } - @hidden table tbl_act { - actions = { - act(); - } - const default_action = act(); - } @hidden table tbl_ingress_drop { actions = { ingress_drop_0(); } const default_action = ingress_drop_0(); } - @hidden table tbl_psaexampleparserchecksum185 { - actions = { - psaexampleparserchecksum185(); - } - const default_action = psaexampleparserchecksum185(); - } apply { - tbl_act.apply(); if (istd.parser_error != error.NoError) { parser_error_count_and_convert_0.apply(); tbl_ingress_drop.apply(); - tbl_psaexampleparserchecksum185.apply(); } } } diff --git a/testdata/p4_16_samples_outputs/psa-switch-expression-without-default-midend.p4 b/testdata/p4_16_samples_outputs/psa-switch-expression-without-default-midend.p4 index cced01c22b..62700cc431 100644 --- a/testdata/p4_16_samples_outputs/psa-switch-expression-without-default-midend.p4 +++ b/testdata/p4_16_samples_outputs/psa-switch-expression-without-default-midend.p4 @@ -81,6 +81,7 @@ parser MyEP(packet_in buffer, out EMPTY a, inout EMPTY b, in psa_egress_parser_i control MyIC(inout headers_t hdr, inout user_meta_t b, in psa_ingress_input_metadata_t c, inout psa_ingress_output_metadata_t d) { @name("MyIC.tmp") bit<16> tmp_0; + bit<16> switch_0_key; @noWarn("unused") @name(".NoAction") action NoAction_1() { } @noWarn("unused") @name(".NoAction") action NoAction_2() { @@ -117,7 +118,6 @@ control MyIC(inout headers_t hdr, inout user_meta_t b, in psa_ingress_input_meta } default_action = NoAction_3(); } - bit<16> switch_0_key; @hidden action switch_0_case() { } @hidden action switch_0_case_0() { diff --git a/testdata/p4_16_samples_outputs/shadow.p4-stderr b/testdata/p4_16_samples_outputs/shadow.p4-stderr index cf8a90eba8..5d7f9a4491 100644 --- a/testdata/p4_16_samples_outputs/shadow.p4-stderr +++ b/testdata/p4_16_samples_outputs/shadow.p4-stderr @@ -1,9 +1,9 @@ shadow.p4(22): [--Wwarn=shadow] warning: 'x' shadows 'x' bit x; - ^^^^^^ + ^^^^^ shadow.p4(20) bit x; - ^^^^^^ + ^^^^^ shadow.p4(17): [--Wwarn=unused] warning: Control c is not used; removing control c() ^ diff --git a/testdata/p4_16_samples_outputs/shadow1.p4-stderr b/testdata/p4_16_samples_outputs/shadow1.p4-stderr index a0fb908bdb..e73e2702de 100644 --- a/testdata/p4_16_samples_outputs/shadow1.p4-stderr +++ b/testdata/p4_16_samples_outputs/shadow1.p4-stderr @@ -1,6 +1,6 @@ shadow1.p4(20): [--Wwarn=shadow] warning: 'counter' shadows 'counter' bit<16> counter; - ^^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^^^^ shadow1.p4(17) extern counter {} ^^^^^^^ diff --git a/testdata/p4_16_samples_outputs/shadow3.p4-stderr b/testdata/p4_16_samples_outputs/shadow3.p4-stderr index d311568826..547771e720 100644 --- a/testdata/p4_16_samples_outputs/shadow3.p4-stderr +++ b/testdata/p4_16_samples_outputs/shadow3.p4-stderr @@ -1,6 +1,6 @@ shadow3.p4(20): [--Wwarn=shadow] warning: 'p' shadows 'p' bit<8> p = 0; - ^^^^^^^^^^^^^ + ^^^^^^^^^^^^ shadow3.p4(19) control MyIngress(inout H p) { ^ diff --git a/testdata/p4_16_samples_outputs/switch-expression-midend.p4 b/testdata/p4_16_samples_outputs/switch-expression-midend.p4 index 29c43ff405..c4ef5dddb2 100644 --- a/testdata/p4_16_samples_outputs/switch-expression-midend.p4 +++ b/testdata/p4_16_samples_outputs/switch-expression-midend.p4 @@ -1,7 +1,6 @@ #include control c(inout bit<32> b) { - bit<32> switch_0_key; @hidden action switch_0_case() { } @hidden action switch_0_case_0() { @@ -10,7 +9,7 @@ control c(inout bit<32> b) { } @hidden table switch_0_table { key = { - switch_0_key: exact; + b: exact; } actions = { switch_0_case(); @@ -34,15 +33,6 @@ control c(inout bit<32> b) { @hidden action switchexpression10() { b = 32w3; } - @hidden action switchexpression5() { - switch_0_key = b; - } - @hidden table tbl_switchexpression5 { - actions = { - switchexpression5(); - } - const default_action = switchexpression5(); - } @hidden table tbl_switchexpression7 { actions = { switchexpression7(); @@ -62,7 +52,6 @@ control c(inout bit<32> b) { const default_action = switchexpression10(); } apply { - tbl_switchexpression5.apply(); switch (switch_0_table.apply().action_run) { switch_0_case: { tbl_switchexpression7.apply();