diff options
Diffstat (limited to 'libyul')
24 files changed, 151 insertions, 80 deletions
diff --git a/libyul/optimiser/CommonSubexpressionEliminator.h b/libyul/optimiser/CommonSubexpressionEliminator.h index ac1ebe3a..4b7973e2 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.h +++ b/libyul/optimiser/CommonSubexpressionEliminator.h @@ -34,6 +34,9 @@ namespace yul */ class CommonSubexpressionEliminator: public DataFlowAnalyzer { +public: + CommonSubexpressionEliminator(Dialect const& _dialect): DataFlowAnalyzer(_dialect) {} + protected: using ASTModifier::visit; void visit(Expression& _e) override; diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index c8d236dc..e97bcdc4 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -142,7 +142,7 @@ void DataFlowAnalyzer::handleAssignment(set<YulString> const& _variables, Expres static Expression const zero{Literal{{}, LiteralKind::Number, YulString{"0"}, {}}}; clearValues(_variables); - MovableChecker movableChecker; + MovableChecker movableChecker{m_dialect}; if (_value) movableChecker.visit(*_value); else diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index 4f12ff6a..5fb5db95 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -30,6 +30,7 @@ namespace yul { +struct Dialect; /** * Base class to perform data flow analysis during AST walks. @@ -43,6 +44,8 @@ namespace yul class DataFlowAnalyzer: public ASTModifier { public: + explicit DataFlowAnalyzer(Dialect const& _dialect): m_dialect(_dialect) {} + using ASTModifier::operator(); void operator()(Assignment& _assignment) override; void operator()(VariableDeclaration& _varDecl) override; @@ -84,6 +87,7 @@ protected: }; /// List of scopes. std::vector<Scope> m_variableScopes; + Dialect const& m_dialect; }; } diff --git a/libyul/optimiser/Disambiguator.cpp b/libyul/optimiser/Disambiguator.cpp index fda5895b..cb56ee99 100644 --- a/libyul/optimiser/Disambiguator.cpp +++ b/libyul/optimiser/Disambiguator.cpp @@ -23,6 +23,7 @@ #include <libyul/Exceptions.h> #include <libyul/AsmData.h> #include <libyul/AsmScope.h> +#include <libyul/Dialect.h> using namespace std; using namespace dev; @@ -31,7 +32,7 @@ using namespace dev::solidity; YulString Disambiguator::translateIdentifier(YulString _originalName) { - if ((m_externallyUsedIdentifiers.count(_originalName))) + if (m_dialect.builtin(_originalName) || m_externallyUsedIdentifiers.count(_originalName)) return _originalName; assertThrow(!m_scopes.empty() && m_scopes.back(), OptimizerException, ""); diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index bb83417b..ec6a0879 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -32,6 +32,7 @@ namespace yul { +struct Dialect; /** * Creates a copy of a Yul AST replacing all identifiers by unique names. @@ -40,10 +41,14 @@ class Disambiguator: public ASTCopier { public: explicit Disambiguator( + Dialect const& _dialect, AsmAnalysisInfo const& _analysisInfo, std::set<YulString> const& _externallyUsedIdentifiers = {} ): - m_info(_analysisInfo), m_externallyUsedIdentifiers(_externallyUsedIdentifiers), m_nameDispenser(m_externallyUsedIdentifiers) + m_info(_analysisInfo), + m_dialect(_dialect), + m_externallyUsedIdentifiers(_externallyUsedIdentifiers), + m_nameDispenser(_dialect, m_externallyUsedIdentifiers) { } @@ -58,6 +63,7 @@ protected: void leaveScopeInternal(Scope& _scope); AsmAnalysisInfo const& m_info; + Dialect const& m_dialect; std::set<YulString> const& m_externallyUsedIdentifiers; std::vector<Scope*> m_scopes; diff --git a/libyul/optimiser/ExpressionInliner.cpp b/libyul/optimiser/ExpressionInliner.cpp index 27d43ac0..858c8733 100644 --- a/libyul/optimiser/ExpressionInliner.cpp +++ b/libyul/optimiser/ExpressionInliner.cpp @@ -56,7 +56,7 @@ void ExpressionInliner::visit(Expression& _expression) bool movable = boost::algorithm::all_of( funCall.arguments, - [=](Expression const& _arg) { return MovableChecker(_arg).movable(); } + [=](Expression const& _arg) { return MovableChecker(m_dialect, _arg).movable(); } ); if (m_inlinableFunctions.count(funCall.functionName.name) && movable) { diff --git a/libyul/optimiser/ExpressionInliner.h b/libyul/optimiser/ExpressionInliner.h index 14e80c0a..e6e710f8 100644 --- a/libyul/optimiser/ExpressionInliner.h +++ b/libyul/optimiser/ExpressionInliner.h @@ -29,6 +29,7 @@ namespace yul { +struct Dialect; /** * Optimiser component that modifies an AST in place, inlining functions that can be @@ -44,8 +45,8 @@ namespace yul class ExpressionInliner: public ASTModifier { public: - ExpressionInliner(Block& _block): - m_block(_block) + ExpressionInliner(Dialect const& _dialect, Block& _block): + m_block(_block), m_dialect(_dialect) {} void run(); @@ -62,6 +63,7 @@ private: std::set<YulString> m_currentFunctions; Block& m_block; + Dialect const& m_dialect; }; diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index cda44e8e..b26e4245 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -36,7 +36,7 @@ using namespace dev::solidity; void ExpressionSimplifier::visit(Expression& _expression) { ASTModifier::visit(_expression); - while (auto match = SimplificationRules::findFirstMatch(_expression, m_ssaValues)) + while (auto match = SimplificationRules::findFirstMatch(_expression, m_dialect, m_ssaValues)) { // Do not apply the rule if it removes non-constant parts of the expression. // TODO: The check could actually be less strict than "movable". @@ -45,15 +45,15 @@ void ExpressionSimplifier::visit(Expression& _expression) // so if the value of the variable is not movable, the expression that references // the variable still is. - if (match->removesNonConstants && !MovableChecker(_expression).movable()) + if (match->removesNonConstants && !MovableChecker(m_dialect, _expression).movable()) return; _expression = match->action().toExpression(locationOf(_expression)); } } -void ExpressionSimplifier::run(Block& _ast) +void ExpressionSimplifier::run(Dialect const& _dialect, Block& _ast) { SSAValueTracker ssaValues; ssaValues(_ast); - ExpressionSimplifier{ssaValues.values()}(_ast); + ExpressionSimplifier{_dialect, ssaValues.values()}(_ast); } diff --git a/libyul/optimiser/ExpressionSimplifier.h b/libyul/optimiser/ExpressionSimplifier.h index fe3507f8..b1122e91 100644 --- a/libyul/optimiser/ExpressionSimplifier.h +++ b/libyul/optimiser/ExpressionSimplifier.h @@ -26,6 +26,7 @@ namespace yul { +struct Dialect; /** * Applies simplification rules to all expressions. @@ -40,12 +41,13 @@ public: using ASTModifier::operator(); virtual void visit(Expression& _expression); - static void run(Block& _ast); + static void run(Dialect const& _dialect, Block& _ast); private: - explicit ExpressionSimplifier(std::map<YulString, Expression const*> _ssaValues): - m_ssaValues(std::move(_ssaValues)) + explicit ExpressionSimplifier(Dialect const& _dialect, std::map<YulString, Expression const*> _ssaValues): + m_dialect(_dialect), m_ssaValues(std::move(_ssaValues)) {} + Dialect const& m_dialect; std::map<YulString, Expression const*> m_ssaValues; }; diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp index e7cdc60f..172e6907 100644 --- a/libyul/optimiser/NameDispenser.cpp +++ b/libyul/optimiser/NameDispenser.cpp @@ -22,17 +22,19 @@ #include <libyul/optimiser/NameCollector.h> #include <libyul/AsmData.h> +#include <libyul/Dialect.h> using namespace std; using namespace dev; using namespace yul; -NameDispenser::NameDispenser(Block const& _ast): - NameDispenser(NameCollector(_ast).names()) +NameDispenser::NameDispenser(Dialect const& _dialect, Block const& _ast): + NameDispenser(_dialect, NameCollector(_ast).names()) { } -NameDispenser::NameDispenser(set<YulString> _usedNames): +NameDispenser::NameDispenser(Dialect const& _dialect, set<YulString> _usedNames): + m_dialect(_dialect), m_usedNames(std::move(_usedNames)) { } @@ -51,7 +53,7 @@ YulString NameDispenser::newName(YulString _nameHint, YulString _context) YulString NameDispenser::newNameInternal(YulString _nameHint) { YulString name = _nameHint; - while (name.empty() || m_usedNames.count(name)) + while (name.empty() || m_usedNames.count(name) || m_dialect.builtin(name)) { m_counter++; name = YulString(_nameHint.str() + "_" + to_string(m_counter)); diff --git a/libyul/optimiser/NameDispenser.h b/libyul/optimiser/NameDispenser.h index 664a5265..719743e6 100644 --- a/libyul/optimiser/NameDispenser.h +++ b/libyul/optimiser/NameDispenser.h @@ -27,6 +27,7 @@ namespace yul { +struct Dialect; /** * Optimizer component that can be used to generate new names that @@ -38,9 +39,9 @@ class NameDispenser { public: /// Initialize the name dispenser with all the names used in the given AST. - explicit NameDispenser(Block const& _ast); + explicit NameDispenser(Dialect const& _dialect, Block const& _ast); /// Initialize the name dispenser with the given used names. - explicit NameDispenser(std::set<YulString> _usedNames); + explicit NameDispenser(Dialect const& _dialect, std::set<YulString> _usedNames); /// @returns a currently unused name that should be similar to _nameHint /// and prefixed by _context if present. @@ -51,6 +52,7 @@ public: private: YulString newNameInternal(YulString _nameHint); + Dialect const& m_dialect; std::set<YulString> m_usedNames; size_t m_counter = 0; }; diff --git a/libyul/optimiser/RedundantAssignEliminator.cpp b/libyul/optimiser/RedundantAssignEliminator.cpp index 7b18e8ca..f6d7676f 100644 --- a/libyul/optimiser/RedundantAssignEliminator.cpp +++ b/libyul/optimiser/RedundantAssignEliminator.cpp @@ -150,9 +150,9 @@ void RedundantAssignEliminator::operator()(Block const& _block) ASTWalker::operator()(_block); } -void RedundantAssignEliminator::run(Block& _ast) +void RedundantAssignEliminator::run(Dialect const& _dialect, Block& _ast) { - RedundantAssignEliminator rae; + RedundantAssignEliminator rae{_dialect}; rae(_ast); AssignmentRemover remover{rae.m_assignmentsToRemove}; @@ -211,7 +211,7 @@ void RedundantAssignEliminator::finalize(YulString _variable) for (auto& assignment: m_assignments[_variable]) { assertThrow(assignment.second != State::Undecided, OptimizerException, ""); - if (assignment.second == State{State::Unused} && MovableChecker{*assignment.first->value}.movable()) + if (assignment.second == State{State::Unused} && MovableChecker{*m_dialect, *assignment.first->value}.movable()) // TODO the only point where we actually need this // to be a set is for the for loop m_assignmentsToRemove.insert(assignment.first); diff --git a/libyul/optimiser/RedundantAssignEliminator.h b/libyul/optimiser/RedundantAssignEliminator.h index 4f82e7a2..2f4dd380 100644 --- a/libyul/optimiser/RedundantAssignEliminator.h +++ b/libyul/optimiser/RedundantAssignEliminator.h @@ -28,6 +28,7 @@ namespace yul { +struct Dialect; /** * Optimiser component that removes assignments to variables that are not used @@ -98,6 +99,7 @@ namespace yul class RedundantAssignEliminator: public ASTWalker { public: + explicit RedundantAssignEliminator(Dialect const& _dialect): m_dialect(&_dialect) {} RedundantAssignEliminator(RedundantAssignEliminator const&) = default; RedundantAssignEliminator& operator=(RedundantAssignEliminator const&) = default; RedundantAssignEliminator(RedundantAssignEliminator&&) = default; @@ -112,7 +114,7 @@ public: void operator()(ForLoop const&) override; void operator()(Block const& _block) override; - static void run(Block& _ast); + static void run(Dialect const& _dialect, Block& _ast); private: RedundantAssignEliminator() = default; @@ -167,6 +169,7 @@ private: void changeUndecidedTo(YulString _variable, State _newState); void finalize(YulString _variable); + Dialect const* m_dialect; std::set<YulString> m_declaredVariables; // TODO check that this does not cause nondeterminism! // This could also be a pseudo-map from state to assignment. diff --git a/libyul/optimiser/Rematerialiser.cpp b/libyul/optimiser/Rematerialiser.cpp index 247defda..56f6e99c 100644 --- a/libyul/optimiser/Rematerialiser.cpp +++ b/libyul/optimiser/Rematerialiser.cpp @@ -30,12 +30,13 @@ using namespace std; using namespace dev; using namespace yul; -void Rematerialiser::run(Block& _ast) +void Rematerialiser::run(Dialect const& _dialect, Block& _ast) { - Rematerialiser{_ast}(_ast); + Rematerialiser{_dialect, _ast}(_ast); } -Rematerialiser::Rematerialiser(Block& _ast): +Rematerialiser::Rematerialiser(Dialect const& _dialect, Block& _ast): + DataFlowAnalyzer(_dialect), m_referenceCounts(ReferencesCounter::countReferences(_ast)) { } diff --git a/libyul/optimiser/Rematerialiser.h b/libyul/optimiser/Rematerialiser.h index c34353de..731697c8 100644 --- a/libyul/optimiser/Rematerialiser.h +++ b/libyul/optimiser/Rematerialiser.h @@ -38,10 +38,10 @@ namespace yul class Rematerialiser: public DataFlowAnalyzer { public: - static void run(Block& _ast); + static void run(Dialect const& _dialect, Block& _ast); protected: - Rematerialiser(Block& _ast); + Rematerialiser(Dialect const& _dialect, Block& _ast); using ASTModifier::visit; void visit(Expression& _e) override; diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index 91bb2709..7edf97d7 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -22,6 +22,7 @@ #include <libyul/Exceptions.h> #include <libyul/AsmData.h> +#include <libyul/Dialect.h> #include <libevmasm/SemanticInformation.h> @@ -31,7 +32,13 @@ using namespace std; using namespace dev; using namespace yul; -MovableChecker::MovableChecker(Expression const& _expression) +MovableChecker::MovableChecker(Dialect const& _dialect): + m_dialect(_dialect) +{ +} + +MovableChecker::MovableChecker(Dialect const& _dialect, Expression const& _expression): + MovableChecker(_dialect) { visit(_expression); } @@ -50,8 +57,14 @@ void MovableChecker::operator()(FunctionalInstruction const& _instr) ASTWalker::operator()(_instr); } -void MovableChecker::operator()(FunctionCall const&) +void MovableChecker::operator()(FunctionCall const& _functionCall) { + if (BuiltinFunction const* f = m_dialect.builtin(_functionCall.functionName.name)) + if (f->movable) + { + ASTWalker::operator()(_functionCall); + return; + } m_movable = false; } diff --git a/libyul/optimiser/Semantics.h b/libyul/optimiser/Semantics.h index 70c50806..a81a489f 100644 --- a/libyul/optimiser/Semantics.h +++ b/libyul/optimiser/Semantics.h @@ -26,6 +26,7 @@ namespace yul { +struct Dialect; /** * Specific AST walker that determines whether an expression is movable. @@ -33,8 +34,8 @@ namespace yul class MovableChecker: public ASTWalker { public: - MovableChecker() = default; - explicit MovableChecker(Expression const& _expression); + explicit MovableChecker(Dialect const& _dialect); + MovableChecker(Dialect const& _dialect, Expression const& _expression); void operator()(Identifier const& _identifier) override; void operator()(FunctionalInstruction const& _functionalInstruction) override; @@ -48,6 +49,7 @@ public: std::set<YulString> const& referencedVariables() const { return m_variableReferences; } private: + Dialect const& m_dialect; /// Which variables the current expression references. std::set<YulString> m_variableReferences; /// Is the current expression movable or not. diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index 45b0ca2c..da9c7d9d 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -36,6 +36,7 @@ using namespace yul; SimplificationRule<Pattern> const* SimplificationRules::findFirstMatch( Expression const& _expr, + Dialect const& _dialect, map<YulString, Expression const*> const& _ssaValues ) { @@ -49,7 +50,7 @@ SimplificationRule<Pattern> const* SimplificationRules::findFirstMatch( for (auto const& rule: rules.m_rules[uint8_t(instruction.instruction)]) { rules.resetMatchGroups(); - if (rule.pattern.matches(_expr, _ssaValues)) + if (rule.pattern.matches(_expr, _dialect, _ssaValues)) return &rule; } return nullptr; @@ -104,7 +105,11 @@ void Pattern::setMatchGroup(unsigned _group, map<unsigned, Expression const*>& _ m_matchGroups = &_matchGroups; } -bool Pattern::matches(Expression const& _expr, map<YulString, Expression const*> const& _ssaValues) const +bool Pattern::matches( + Expression const& _expr, + Dialect const& _dialect, + map<YulString, Expression const*> const& _ssaValues +) const { Expression const* expr = &_expr; @@ -139,7 +144,7 @@ bool Pattern::matches(Expression const& _expr, map<YulString, Expression const*> return false; assertThrow(m_arguments.size() == instr.arguments.size(), OptimizerException, ""); for (size_t i = 0; i < m_arguments.size(); ++i) - if (!m_arguments[i].matches(instr.arguments.at(i), _ssaValues)) + if (!m_arguments[i].matches(instr.arguments.at(i), _dialect, _ssaValues)) return false; } else @@ -167,7 +172,7 @@ bool Pattern::matches(Expression const& _expr, map<YulString, Expression const*> assertThrow(firstMatch, OptimizerException, "Match set but to null."); return SyntacticalEqualityChecker::equal(*firstMatch, _expr) && - MovableChecker(_expr).movable(); + MovableChecker(_dialect, _expr).movable(); } else if (m_kind == PatternKind::Any) (*m_matchGroups)[m_matchGroup] = &_expr; diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index 16aaba04..8213a185 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -33,7 +33,7 @@ namespace yul { - +struct Dialect; class Pattern; /** @@ -49,6 +49,7 @@ public: /// @param _ssaValues values of variables that are assigned exactly once. static SimplificationRule<Pattern> const* findFirstMatch( Expression const& _expr, + Dialect const& _dialect, std::map<YulString, Expression const*> const& _ssaValues ); @@ -93,7 +94,11 @@ public: /// same expression equivalence class. void setMatchGroup(unsigned _group, std::map<unsigned, Expression const*>& _matchGroups); unsigned matchGroup() const { return m_matchGroup; } - bool matches(Expression const& _expr, std::map<YulString, Expression const*> const& _ssaValues) const; + bool matches( + Expression const& _expr, + Dialect const& _dialect, + std::map<YulString, Expression const*> const& _ssaValues + ) const; std::vector<Pattern> arguments() const { return m_arguments; } diff --git a/libyul/optimiser/StructuralSimplifier.h b/libyul/optimiser/StructuralSimplifier.h index bbd8e005..d68a9620 100644 --- a/libyul/optimiser/StructuralSimplifier.h +++ b/libyul/optimiser/StructuralSimplifier.h @@ -38,6 +38,8 @@ namespace yul class StructuralSimplifier: public DataFlowAnalyzer { public: + explicit StructuralSimplifier(Dialect const& _dialect): DataFlowAnalyzer(_dialect) {} + using DataFlowAnalyzer::operator(); void operator()(Block& _block) override; private: diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index c0fd15a2..9b6e1337 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -47,6 +47,7 @@ using namespace dev; using namespace yul; void OptimiserSuite::run( + Dialect const& _dialect, Block& _ast, AsmAnalysisInfo const& _analysisInfo, set<YulString> const& _externallyUsedIdentifiers @@ -54,69 +55,69 @@ void OptimiserSuite::run( { set<YulString> reservedIdentifiers = _externallyUsedIdentifiers; - Block ast = boost::get<Block>(Disambiguator(_analysisInfo, reservedIdentifiers)(_ast)); + Block ast = boost::get<Block>(Disambiguator(_dialect, _analysisInfo, reservedIdentifiers)(_ast)); (VarDeclInitializer{})(ast); (FunctionHoister{})(ast); (FunctionGrouper{})(ast); (ForLoopInitRewriter{})(ast); - StructuralSimplifier{}(ast); + StructuralSimplifier{_dialect}(ast); - NameDispenser dispenser{ast}; + NameDispenser dispenser{_dialect, ast}; for (size_t i = 0; i < 4; i++) { ExpressionSplitter{dispenser}(ast); SSATransform::run(ast, dispenser); - RedundantAssignEliminator::run(ast); - RedundantAssignEliminator::run(ast); + RedundantAssignEliminator::run(_dialect, ast); + RedundantAssignEliminator::run(_dialect, ast); - CommonSubexpressionEliminator{}(ast); - ExpressionSimplifier::run(ast); - StructuralSimplifier{}(ast); + CommonSubexpressionEliminator{_dialect}(ast); + ExpressionSimplifier::run(_dialect, ast); + StructuralSimplifier{_dialect}(ast); SSATransform::run(ast, dispenser); - RedundantAssignEliminator::run(ast); - RedundantAssignEliminator::run(ast); - UnusedPruner::runUntilStabilised(ast, reservedIdentifiers); - CommonSubexpressionEliminator{}(ast); - UnusedPruner::runUntilStabilised(ast, reservedIdentifiers); + RedundantAssignEliminator::run(_dialect, ast); + RedundantAssignEliminator::run(_dialect, ast); + UnusedPruner::runUntilStabilised(_dialect, ast, reservedIdentifiers); + CommonSubexpressionEliminator{_dialect}(ast); + UnusedPruner::runUntilStabilised(_dialect, ast, reservedIdentifiers); SSATransform::run(ast, dispenser); - RedundantAssignEliminator::run(ast); - RedundantAssignEliminator::run(ast); + RedundantAssignEliminator::run(_dialect, ast); + RedundantAssignEliminator::run(_dialect, ast); ExpressionJoiner::run(ast); ExpressionJoiner::run(ast); - ExpressionInliner(ast).run(); - UnusedPruner::runUntilStabilised(ast); + ExpressionInliner(_dialect, ast).run(); + UnusedPruner::runUntilStabilised(_dialect, ast); ExpressionSplitter{dispenser}(ast); SSATransform::run(ast, dispenser); - RedundantAssignEliminator::run(ast); - RedundantAssignEliminator::run(ast); - CommonSubexpressionEliminator{}(ast); + RedundantAssignEliminator::run(_dialect, ast); + RedundantAssignEliminator::run(_dialect, ast); + CommonSubexpressionEliminator{_dialect}(ast); FullInliner{ast, dispenser}.run(); SSATransform::run(ast, dispenser); - RedundantAssignEliminator::run(ast); - RedundantAssignEliminator::run(ast); - ExpressionSimplifier::run(ast); - StructuralSimplifier{}(ast); - CommonSubexpressionEliminator{}(ast); + RedundantAssignEliminator::run(_dialect, ast); + RedundantAssignEliminator::run(_dialect, ast); + ExpressionSimplifier::run(_dialect, ast); + StructuralSimplifier{_dialect}(ast); + CommonSubexpressionEliminator{_dialect}(ast); SSATransform::run(ast, dispenser); - RedundantAssignEliminator::run(ast); - RedundantAssignEliminator::run(ast); - UnusedPruner::runUntilStabilised(ast, reservedIdentifiers); - CommonSubexpressionEliminator{}(ast); + RedundantAssignEliminator::run(_dialect, ast); + RedundantAssignEliminator::run(_dialect, ast); + UnusedPruner::runUntilStabilised(_dialect, ast, reservedIdentifiers); + CommonSubexpressionEliminator{_dialect}(ast); } ExpressionJoiner::run(ast); - Rematerialiser::run(ast); - UnusedPruner::runUntilStabilised(ast); + Rematerialiser::run(_dialect, ast); + UnusedPruner::runUntilStabilised(_dialect, ast); ExpressionJoiner::run(ast); - UnusedPruner::runUntilStabilised(ast); + UnusedPruner::runUntilStabilised(_dialect, ast); ExpressionJoiner::run(ast); - UnusedPruner::runUntilStabilised(ast); + UnusedPruner::runUntilStabilised(_dialect, ast); ExpressionJoiner::run(ast); - Rematerialiser::run(ast); - UnusedPruner::runUntilStabilised(ast); + Rematerialiser::run(_dialect, ast); + UnusedPruner::runUntilStabilised(_dialect, ast); _ast = std::move(ast); } diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 795326b4..ce40b204 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -29,6 +29,7 @@ namespace yul { struct AsmAnalysisInfo; +struct Dialect; /** * Optimiser suite that combines all steps and also provides the settings for the heuristics @@ -37,6 +38,7 @@ class OptimiserSuite { public: static void run( + Dialect const& _dialect, Block& _ast, AsmAnalysisInfo const& _analysisInfo, diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index 31aead82..53c412e3 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -32,7 +32,8 @@ using namespace std; using namespace dev; using namespace yul; -UnusedPruner::UnusedPruner(Block& _ast, set<YulString> const& _externallyUsedFunctions) +UnusedPruner::UnusedPruner(Dialect const& _dialect, Block& _ast, set<YulString> const& _externallyUsedFunctions): + m_dialect(_dialect) { ReferencesCounter counter; counter(_ast); @@ -69,7 +70,7 @@ void UnusedPruner::operator()(Block& _block) { if (!varDecl.value) statement = Block{std::move(varDecl.location), {}}; - else if (MovableChecker(*varDecl.value).movable()) + else if (MovableChecker(m_dialect, *varDecl.value).movable()) { subtractReferences(ReferencesCounter::countReferences(*varDecl.value)); statement = Block{std::move(varDecl.location), {}}; @@ -87,7 +88,7 @@ void UnusedPruner::operator()(Block& _block) else if (statement.type() == typeid(ExpressionStatement)) { ExpressionStatement& exprStmt = boost::get<ExpressionStatement>(statement); - if (MovableChecker(exprStmt.expression).movable()) + if (MovableChecker(m_dialect, exprStmt.expression).movable()) { // pop(x) should be movable! subtractReferences(ReferencesCounter::countReferences(exprStmt.expression)); @@ -100,11 +101,15 @@ void UnusedPruner::operator()(Block& _block) ASTModifier::operator()(_block); } -void UnusedPruner::runUntilStabilised(Block& _ast, set<YulString> const& _externallyUsedFunctions) +void UnusedPruner::runUntilStabilised( + Dialect const& _dialect, + Block& _ast, + set<YulString> const& _externallyUsedFunctions +) { while (true) { - UnusedPruner pruner(_ast, _externallyUsedFunctions); + UnusedPruner pruner(_dialect, _ast, _externallyUsedFunctions); pruner(_ast); if (!pruner.shouldRunAgain()) return; diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index 64e02b35..72279d4a 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -28,6 +28,7 @@ namespace yul { +struct Dialect; /** * Optimisation stage that removes unused variables and functions and also @@ -40,7 +41,11 @@ namespace yul class UnusedPruner: public ASTModifier { public: - explicit UnusedPruner(Block& _ast, std::set<YulString> const& _externallyUsedFunctions = {}); + UnusedPruner( + Dialect const& _dialect, + Block& _ast, + std::set<YulString> const& _externallyUsedFunctions = {} + ); using ASTModifier::operator(); void operator()(Block& _block) override; @@ -49,12 +54,17 @@ public: bool shouldRunAgain() const { return m_shouldRunAgain; } // Run the pruner until the code does not change anymore. - static void runUntilStabilised(Block& _ast, std::set<YulString> const& _externallyUsedFunctions = {}); + static void runUntilStabilised( + Dialect const& _dialect, + Block& _ast, + std::set<YulString> const& _externallyUsedFunctions = {} + ); private: bool used(YulString _name) const; void subtractReferences(std::map<YulString, size_t> const& _subtrahend); + Dialect const& m_dialect; bool m_shouldRunAgain = false; std::map<YulString, size_t> m_references; }; |