mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #7833 from ethereum/combineValueAndLoopDepth
Combine value and loop depth
This commit is contained in:
commit
17158995b5
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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, "");
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user