Merge pull request #7833 from ethereum/combineValueAndLoopDepth

Combine value and loop depth
This commit is contained in:
chriseth 2020-01-09 13:01:22 +01:00 committed by GitHub
commit 17158995b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 38 additions and 35 deletions

View File

@ -79,10 +79,10 @@ void CommonSubexpressionEliminator::visit(Expression& _e)
YulString name = identifier.name;
if (m_value.count(name))
{
assertThrow(m_value.at(name), OptimizerException, "");
if (holds_alternative<Identifier>(*m_value.at(name)))
assertThrow(m_value.at(name).value, OptimizerException, "");
if (holds_alternative<Identifier>(*m_value.at(name).value))
{
YulString value = std::get<Identifier>(*m_value.at(name)).name;
YulString value = std::get<Identifier>(*m_value.at(name).value).name;
assertThrow(inScope(value), OptimizerException, "");
_e = Identifier{locationOf(_e), value};
}
@ -91,13 +91,13 @@ void CommonSubexpressionEliminator::visit(Expression& _e)
else
{
// TODO this search is rather inefficient.
for (auto const& var: m_value)
for (auto const& [variable, value]: m_value)
{
assertThrow(var.second, OptimizerException, "");
assertThrow(inScope(var.first), OptimizerException, "");
if (SyntacticallyEqual{}(_e, *var.second))
assertThrow(value.value, OptimizerException, "");
assertThrow(inScope(variable), OptimizerException, "");
if (SyntacticallyEqual{}(_e, *value.value))
{
_e = Identifier{locationOf(_e), var.first};
_e = Identifier{locationOf(_e), variable};
break;
}
}

View File

@ -144,14 +144,12 @@ void DataFlowAnalyzer::operator()(FunctionDefinition& _fun)
{
// Save all information. We might rather reinstantiate this class,
// but this could be difficult if it is subclassed.
map<YulString, Expression const*> value;
map<YulString, size_t> variableLoopDepth;
map<YulString, AssignedValue> value;
size_t loopDepth{0};
InvertibleRelation<YulString> references;
InvertibleMap<YulString, YulString> storage;
InvertibleMap<YulString, YulString> memory;
swap(m_value, value);
swap(m_variableLoopDepth, variableLoopDepth);
swap(m_loopDepth, loopDepth);
swap(m_references, references);
swap(m_storage, storage);
@ -173,7 +171,6 @@ void DataFlowAnalyzer::operator()(FunctionDefinition& _fun)
popScope();
swap(m_value, value);
swap(m_variableLoopDepth, variableLoopDepth);
swap(m_loopDepth, loopDepth);
swap(m_references, references);
swap(m_storage, storage);
@ -306,18 +303,14 @@ void DataFlowAnalyzer::clearValues(set<YulString> _variables)
// Clear the value and update the reference relation.
for (auto const& name: _variables)
{
m_value.erase(name);
m_variableLoopDepth.erase(name);
}
for (auto const& name: _variables)
m_references.eraseKey(name);
}
void DataFlowAnalyzer::assignValue(YulString _variable, Expression const* _value)
{
m_value[_variable] = _value;
m_variableLoopDepth[_variable] = m_loopDepth;
m_value[_variable] = {_value, m_loopDepth};
}
void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Block const& _block)

View File

@ -41,6 +41,14 @@ namespace solidity::yul
struct Dialect;
struct SideEffects;
/// Value assigned to a variable.
struct AssignedValue
{
Expression const* value{nullptr};
/// Loop nesting depth of the definition of the variable.
size_t loopDepth{0};
};
/**
* Base class to perform data flow analysis during AST walks.
* Tracks assignments and is used as base class for both Rematerialiser and
@ -145,9 +153,7 @@ protected:
std::map<YulString, SideEffects> m_functionSideEffects;
/// Current values of variables, always movable.
std::map<YulString, Expression const*> m_value;
/// The loop nesting depth of the definition of variables (those used in m_value).
std::map<YulString, size_t> m_variableLoopDepth;
std::map<YulString, AssignedValue> m_value;
/// m_references.forward[a].contains(b) <=> the current expression assigned to a references b
/// m_references.backward[b].contains(a) <=> the current expression assigned to a references b
InvertibleRelation<YulString> m_references;

View File

@ -23,6 +23,7 @@
#include <libyul/AsmData.h>
#include <libyul/Utilities.h>
#include <libyul/optimiser/SimplificationRules.h>
#include <libyul/optimiser/DataFlowAnalyzer.h>
#include <libyul/optimiser/Semantics.h>
#include <libsolutil/CommonData.h>

View File

@ -28,6 +28,7 @@ namespace solidity::yul
{
struct Dialect;
struct AssignedValue;
/**
* Class that can answer questions about values of variables and their relations.
@ -37,7 +38,7 @@ struct Dialect;
class KnowledgeBase
{
public:
KnowledgeBase(Dialect const& _dialect, std::map<YulString, Expression const*> const& _variableValues):
KnowledgeBase(Dialect const& _dialect, std::map<YulString, AssignedValue> const& _variableValues):
m_dialect(_dialect),
m_variableValues(_variableValues)
{}
@ -50,7 +51,7 @@ private:
Expression simplify(Expression _expression);
Dialect const& m_dialect;
std::map<YulString, Expression const*> const& m_variableValues;
std::map<YulString, AssignedValue> const& m_variableValues;
size_t m_recursionCounter = 0;
};

View File

@ -74,12 +74,12 @@ void Rematerialiser::visit(Expression& _e)
YulString name = identifier.name;
if (m_value.count(name))
{
assertThrow(m_value.at(name), OptimizerException, "");
auto const& value = *m_value.at(name);
assertThrow(m_value.at(name).value, OptimizerException, "");
AssignedValue const& value = m_value.at(name);
size_t refs = m_referenceCounts[name];
size_t cost = CodeCost::codeCost(m_dialect, value);
size_t cost = CodeCost::codeCost(m_dialect, *value.value);
if (
(refs <= 1 && m_variableLoopDepth.at(name) == m_loopDepth) ||
(refs <= 1 && value.loopDepth == m_loopDepth) ||
cost == 0 ||
(refs <= 5 && cost <= 1 && m_loopDepth == 0) ||
m_varsToAlwaysRematerialize.count(name)
@ -90,9 +90,9 @@ void Rematerialiser::visit(Expression& _e)
assertThrow(inScope(ref), OptimizerException, "");
// update reference counts
m_referenceCounts[name]--;
for (auto const& ref: ReferencesCounter::countReferences(value))
for (auto const& ref: ReferencesCounter::countReferences(*value.value))
m_referenceCounts[ref.first] += ref.second;
_e = (ASTCopier{}).translate(value);
_e = (ASTCopier{}).translate(*value.value);
}
}
}
@ -107,7 +107,7 @@ void LiteralRematerialiser::visit(Expression& _e)
YulString name = identifier.name;
if (m_value.count(name))
{
Expression const* value = m_value.at(name);
Expression const* value = m_value.at(name).value;
assertThrow(value, OptimizerException, "");
if (holds_alternative<Literal>(*value))
_e = *value;

View File

@ -23,6 +23,7 @@
#include <libyul/optimiser/ASTCopier.h>
#include <libyul/optimiser/Semantics.h>
#include <libyul/optimiser/SyntacticalEquality.h>
#include <libyul/optimiser/DataFlowAnalyzer.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <libyul/AsmData.h>
#include <libyul/Utilities.h>
@ -38,7 +39,7 @@ using namespace solidity::yul;
SimplificationRule<yul::Pattern> const* SimplificationRules::findFirstMatch(
Expression const& _expr,
Dialect const& _dialect,
map<YulString, Expression const*> const& _ssaValues
map<YulString, AssignedValue> const& _ssaValues
)
{
auto instruction = instructionAndArguments(_dialect, _expr);
@ -126,7 +127,7 @@ void Pattern::setMatchGroup(unsigned _group, map<unsigned, Expression const*>& _
bool Pattern::matches(
Expression const& _expr,
Dialect const& _dialect,
map<YulString, Expression const*> const& _ssaValues
map<YulString, AssignedValue> const& _ssaValues
) const
{
Expression const* expr = &_expr;
@ -137,7 +138,7 @@ bool Pattern::matches(
{
YulString varName = std::get<Identifier>(_expr).name;
if (_ssaValues.count(varName))
if (Expression const* new_expr = _ssaValues.at(varName))
if (Expression const* new_expr = _ssaValues.at(varName).value)
expr = new_expr;
}
assertThrow(expr, OptimizerException, "");

View File

@ -36,6 +36,7 @@
namespace solidity::yul
{
struct Dialect;
struct AssignedValue;
class Pattern;
/**
@ -52,7 +53,7 @@ public:
static evmasm::SimplificationRule<Pattern> const* findFirstMatch(
Expression const& _expr,
Dialect const& _dialect,
std::map<YulString, Expression const*> const& _ssaValues
std::map<YulString, AssignedValue> const& _ssaValues
);
/// Checks whether the rulelist is non-empty. This is usually enforced
@ -109,7 +110,7 @@ public:
bool matches(
Expression const& _expr,
Dialect const& _dialect,
std::map<YulString, Expression const*> const& _ssaValues
std::map<YulString, AssignedValue> const& _ssaValues
) const;
std::vector<Pattern> arguments() const { return m_arguments; }

View File

@ -70,7 +70,7 @@ public:
{
YulString varName = _varDecl.variables.front().name;
if (m_value.count(varName))
m_expressionCodeCost[varName] = CodeCost::codeCost(m_dialect, *m_value[varName]);
m_expressionCodeCost[varName] = CodeCost::codeCost(m_dialect, *m_value[varName].value);
}
}