Skip to content

Commit c12d151

Browse files
committed
Only analyze memory in DataFlowAnalyzer if it is needed in the optimizer step.
1 parent e7c5f04 commit c12d151

9 files changed

+56
-37
lines changed

libyul/optimiser/CommonSubexpressionEliminator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ CommonSubexpressionEliminator::CommonSubexpressionEliminator(
4848
Dialect const& _dialect,
4949
map<YulString, SideEffects> _functionSideEffects
5050
):
51-
DataFlowAnalyzer(_dialect, std::move(_functionSideEffects))
51+
DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore, std::move(_functionSideEffects))
5252
{
5353
}
5454

libyul/optimiser/DataFlowAnalyzer.cpp

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -44,47 +44,54 @@ using namespace solidity::yul;
4444

4545
DataFlowAnalyzer::DataFlowAnalyzer(
4646
Dialect const& _dialect,
47+
MemoryAndStorage _analyzeStores,
4748
map<YulString, SideEffects> _functionSideEffects
4849
):
4950
m_dialect(_dialect),
5051
m_functionSideEffects(std::move(_functionSideEffects)),
51-
m_knowledgeBase(_dialect, [this](YulString _var) { return variableValue(_var); })
52+
m_knowledgeBase(_dialect, [this](YulString _var) { return variableValue(_var); }),
53+
m_analyzeStores(_analyzeStores == MemoryAndStorage::Analyze)
5254
{
53-
if (auto const* builtin = _dialect.memoryStoreFunction(YulString{}))
54-
m_storeFunctionName[static_cast<unsigned>(StoreLoadLocation::Memory)] = builtin->name;
55-
if (auto const* builtin = _dialect.memoryLoadFunction(YulString{}))
56-
m_loadFunctionName[static_cast<unsigned>(StoreLoadLocation::Memory)] = builtin->name;
57-
if (auto const* builtin = _dialect.storageStoreFunction(YulString{}))
58-
m_storeFunctionName[static_cast<unsigned>(StoreLoadLocation::Storage)] = builtin->name;
59-
if (auto const* builtin = _dialect.storageLoadFunction(YulString{}))
60-
m_loadFunctionName[static_cast<unsigned>(StoreLoadLocation::Storage)] = builtin->name;
55+
if (m_analyzeStores)
56+
{
57+
if (auto const* builtin = _dialect.memoryStoreFunction(YulString{}))
58+
m_storeFunctionName[static_cast<unsigned>(StoreLoadLocation::Memory)] = builtin->name;
59+
if (auto const* builtin = _dialect.memoryLoadFunction(YulString{}))
60+
m_loadFunctionName[static_cast<unsigned>(StoreLoadLocation::Memory)] = builtin->name;
61+
if (auto const* builtin = _dialect.storageStoreFunction(YulString{}))
62+
m_storeFunctionName[static_cast<unsigned>(StoreLoadLocation::Storage)] = builtin->name;
63+
if (auto const* builtin = _dialect.storageLoadFunction(YulString{}))
64+
m_loadFunctionName[static_cast<unsigned>(StoreLoadLocation::Storage)] = builtin->name;
65+
}
6166
}
6267

6368
void DataFlowAnalyzer::operator()(ExpressionStatement& _statement)
6469
{
65-
if (auto vars = isSimpleStore(StoreLoadLocation::Storage, _statement))
66-
{
67-
ASTModifier::operator()(_statement);
68-
cxx20::erase_if(m_state.storage, mapTuple([&](auto&& key, auto&& value) {
69-
return
70-
!m_knowledgeBase.knownToBeDifferent(vars->first, key) &&
71-
!m_knowledgeBase.knownToBeEqual(vars->second, value);
72-
}));
73-
m_state.storage[vars->first] = vars->second;
74-
}
75-
else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, _statement))
70+
if (m_analyzeStores)
7671
{
77-
ASTModifier::operator()(_statement);
78-
cxx20::erase_if(m_state.memory, mapTuple([&](auto&& key, auto&& /* value */) {
79-
return !m_knowledgeBase.knownToBeDifferentByAtLeast32(vars->first, key);
80-
}));
81-
m_state.memory[vars->first] = vars->second;
82-
}
83-
else
84-
{
85-
clearKnowledgeIfInvalidated(_statement.expression);
86-
ASTModifier::operator()(_statement);
72+
if (auto vars = isSimpleStore(StoreLoadLocation::Storage, _statement))
73+
{
74+
ASTModifier::operator()(_statement);
75+
cxx20::erase_if(m_state.storage, mapTuple([&](auto&& key, auto&& value) {
76+
return
77+
!m_knowledgeBase.knownToBeDifferent(vars->first, key) &&
78+
!m_knowledgeBase.knownToBeEqual(vars->second, value);
79+
}));
80+
m_state.storage[vars->first] = vars->second;
81+
return;
82+
}
83+
else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, _statement))
84+
{
85+
ASTModifier::operator()(_statement);
86+
cxx20::erase_if(m_state.memory, mapTuple([&](auto&& key, auto&& /* value */) {
87+
return !m_knowledgeBase.knownToBeDifferentByAtLeast32(vars->first, key);
88+
}));
89+
m_state.memory[vars->first] = vars->second;
90+
return;
91+
}
8792
}
93+
clearKnowledgeIfInvalidated(_statement.expression);
94+
ASTModifier::operator()(_statement);
8895
}
8996

9097
void DataFlowAnalyzer::operator()(Assignment& _assignment)
@@ -346,6 +353,8 @@ void DataFlowAnalyzer::assignValue(YulString _variable, Expression const* _value
346353

347354
void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Block const& _block)
348355
{
356+
if (!m_analyzeStores)
357+
return;
349358
SideEffectsCollector sideEffects(m_dialect, _block, &m_functionSideEffects);
350359
if (sideEffects.invalidatesStorage())
351360
m_state.storage.clear();
@@ -355,6 +364,8 @@ void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Block const& _block)
355364

356365
void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Expression const& _expr)
357366
{
367+
if (!m_analyzeStores)
368+
return;
358369
SideEffectsCollector sideEffects(m_dialect, _expr, &m_functionSideEffects);
359370
if (sideEffects.invalidatesStorage())
360371
m_state.storage.clear();
@@ -367,6 +378,8 @@ void DataFlowAnalyzer::joinKnowledge(
367378
unordered_map<YulString, YulString> const& _olderMemory
368379
)
369380
{
381+
if (!m_analyzeStores)
382+
return;
370383
joinKnowledgeHelper(m_state.storage, _olderStorage);
371384
joinKnowledgeHelper(m_state.memory, _olderMemory);
372385
}

libyul/optimiser/DataFlowAnalyzer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,14 @@ struct AssignedValue
8181
class DataFlowAnalyzer: public ASTModifier
8282
{
8383
public:
84+
enum class MemoryAndStorage { Analyze, Ignore };
8485
/// @param _functionSideEffects
8586
/// Side-effects of user-defined functions. Worst-case side-effects are assumed
8687
/// if this is not provided or the function is not found.
8788
/// The parameter is mostly used to determine movability of expressions.
8889
explicit DataFlowAnalyzer(
8990
Dialect const& _dialect,
91+
MemoryAndStorage _analyzeStores,
9092
std::map<YulString, SideEffects> _functionSideEffects = {}
9193
);
9294

@@ -189,6 +191,8 @@ class DataFlowAnalyzer: public ASTModifier
189191
protected:
190192
KnowledgeBase m_knowledgeBase;
191193

194+
/// If true, analyzes memory and storage content via mload/mstore and sload/sstore.
195+
bool m_analyzeStores = true;
192196
YulString m_storeFunctionName[static_cast<unsigned>(StoreLoadLocation::Last) + 1];
193197
YulString m_loadFunctionName[static_cast<unsigned>(StoreLoadLocation::Last) + 1];
194198

libyul/optimiser/EqualStoreEliminator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class EqualStoreEliminator: public DataFlowAnalyzer
4747
Dialect const& _dialect,
4848
std::map<YulString, SideEffects> _functionSideEffects
4949
):
50-
DataFlowAnalyzer(_dialect, std::move(_functionSideEffects))
50+
DataFlowAnalyzer(_dialect, MemoryAndStorage::Analyze, std::move(_functionSideEffects))
5151
{}
5252

5353
protected:

libyul/optimiser/ExpressionSimplifier.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ class ExpressionSimplifier: public DataFlowAnalyzer
5151
void visit(Expression& _expression) override;
5252

5353
private:
54-
explicit ExpressionSimplifier(Dialect const& _dialect): DataFlowAnalyzer(_dialect) {}
54+
explicit ExpressionSimplifier(Dialect const& _dialect):
55+
DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore)
56+
{}
5557
};
5658

5759
}

libyul/optimiser/LoadResolver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class LoadResolver: public DataFlowAnalyzer
5353
bool _containsMSize,
5454
std::optional<size_t> _expectedExecutionsPerDeployment
5555
):
56-
DataFlowAnalyzer(_dialect, std::move(_functionSideEffects)),
56+
DataFlowAnalyzer(_dialect, MemoryAndStorage::Analyze, std::move(_functionSideEffects)),
5757
m_containsMSize(_containsMSize),
5858
m_expectedExecutionsPerDeployment(std::move(_expectedExecutionsPerDeployment))
5959
{}

libyul/optimiser/Rematerialiser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Rematerialiser::Rematerialiser(
4343
set<YulString> _varsToAlwaysRematerialize,
4444
bool _onlySelectedVariables
4545
):
46-
DataFlowAnalyzer(_dialect),
46+
DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore),
4747
m_referenceCounts(ReferencesCounter::countReferences(_ast)),
4848
m_varsToAlwaysRematerialize(std::move(_varsToAlwaysRematerialize)),
4949
m_onlySelectedVariables(_onlySelectedVariables)

libyul/optimiser/Rematerialiser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class LiteralRematerialiser: public DataFlowAnalyzer
9595

9696
private:
9797
LiteralRematerialiser(Dialect const& _dialect):
98-
DataFlowAnalyzer(_dialect)
98+
DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore)
9999
{}
100100
};
101101

libyul/optimiser/StackCompressor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ namespace
5656
class RematCandidateSelector: public DataFlowAnalyzer
5757
{
5858
public:
59-
explicit RematCandidateSelector(Dialect const& _dialect): DataFlowAnalyzer(_dialect) {}
59+
explicit RematCandidateSelector(Dialect const& _dialect): DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore) {}
6060

6161
/// @returns a map from function name to rematerialisation costs to a vector of variables to rematerialise
6262
/// and variables that occur in their expression.

0 commit comments

Comments
 (0)