mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Make the dialect available everywhere.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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, "");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
+36
-35
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user