Skip to content

Commit afdf22f

Browse files
committed
Create a state struct.
1 parent eab4ca9 commit afdf22f

File tree

2 files changed

+49
-47
lines changed

2 files changed

+49
-47
lines changed

libyul/optimiser/DataFlowAnalyzer.cpp

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,20 @@ void DataFlowAnalyzer::operator()(ExpressionStatement& _statement)
6565
if (auto vars = isSimpleStore(StoreLoadLocation::Storage, _statement))
6666
{
6767
ASTModifier::operator()(_statement);
68-
cxx20::erase_if(m_storage, mapTuple([&](auto&& key, auto&& value) {
68+
cxx20::erase_if(m_state.storage, mapTuple([&](auto&& key, auto&& value) {
6969
return
7070
!m_knowledgeBase.knownToBeDifferent(vars->first, key) &&
7171
!m_knowledgeBase.knownToBeEqual(vars->second, value);
7272
}));
73-
m_storage[vars->first] = vars->second;
73+
m_state.storage[vars->first] = vars->second;
7474
}
7575
else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, _statement))
7676
{
7777
ASTModifier::operator()(_statement);
78-
cxx20::erase_if(m_memory, mapTuple([&](auto&& key, auto&& /* value */) {
78+
cxx20::erase_if(m_state.memory, mapTuple([&](auto&& key, auto&& /* value */) {
7979
return !m_knowledgeBase.knownToBeDifferentByAtLeast32(vars->first, key);
8080
}));
81-
m_memory[vars->first] = vars->second;
81+
m_state.memory[vars->first] = vars->second;
8282
}
8383
else
8484
{
@@ -117,8 +117,8 @@ void DataFlowAnalyzer::operator()(VariableDeclaration& _varDecl)
117117
void DataFlowAnalyzer::operator()(If& _if)
118118
{
119119
clearKnowledgeIfInvalidated(*_if.condition);
120-
unordered_map<YulString, YulString> storage = m_storage;
121-
unordered_map<YulString, YulString> memory = m_memory;
120+
unordered_map<YulString, YulString> storage = m_state.storage;
121+
unordered_map<YulString, YulString> memory = m_state.memory;
122122

123123
ASTModifier::operator()(_if);
124124

@@ -134,8 +134,8 @@ void DataFlowAnalyzer::operator()(Switch& _switch)
134134
set<YulString> assignedVariables;
135135
for (auto& _case: _switch.cases)
136136
{
137-
unordered_map<YulString, YulString> storage = m_storage;
138-
unordered_map<YulString, YulString> memory = m_memory;
137+
unordered_map<YulString, YulString> storage = m_state.storage;
138+
unordered_map<YulString, YulString> memory = m_state.memory;
139139
(*this)(_case.body);
140140
joinKnowledge(storage, memory);
141141

@@ -154,11 +154,8 @@ void DataFlowAnalyzer::operator()(FunctionDefinition& _fun)
154154
{
155155
// Save all information. We might rather reinstantiate this class,
156156
// but this could be difficult if it is subclassed.
157-
ScopedSaveAndRestore valueResetter(m_value, {});
157+
ScopedSaveAndRestore stateResetter(m_state, {});
158158
ScopedSaveAndRestore loopDepthResetter(m_loopDepth, 0u);
159-
ScopedSaveAndRestore referencesResetter(m_references, {});
160-
ScopedSaveAndRestore storageResetter(m_storage, {});
161-
ScopedSaveAndRestore memoryResetter(m_memory, {});
162159
pushScope(true);
163160

164161
for (auto const& parameter: _fun.parameters)
@@ -221,15 +218,15 @@ void DataFlowAnalyzer::operator()(Block& _block)
221218

222219
optional<YulString> DataFlowAnalyzer::storageValue(YulString _key) const
223220
{
224-
if (YulString const* value = util::valueOrNullptr(m_storage, _key))
221+
if (YulString const* value = util::valueOrNullptr(m_state.storage, _key))
225222
return *value;
226223
else
227224
return nullopt;
228225
}
229226

230227
optional<YulString> DataFlowAnalyzer::memoryValue(YulString _key) const
231228
{
232-
if (YulString const* value = util::valueOrNullptr(m_memory, _key))
229+
if (YulString const* value = util::valueOrNullptr(m_state.memory, _key))
233230
return *value;
234231
else
235232
return nullopt;
@@ -259,17 +256,17 @@ void DataFlowAnalyzer::handleAssignment(set<YulString> const& _variables, Expres
259256
auto const& referencedVariables = movableChecker.referencedVariables();
260257
for (auto const& name: _variables)
261258
{
262-
m_references[name] = referencedVariables;
259+
m_state.references[name] = referencedVariables;
263260
if (!_isDeclaration)
264261
{
265262
// assignment to slot denoted by "name"
266-
m_storage.erase(name);
263+
m_state.storage.erase(name);
267264
// assignment to slot contents denoted by "name"
268-
cxx20::erase_if(m_storage, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; }));
265+
cxx20::erase_if(m_state.storage, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; }));
269266
// assignment to slot denoted by "name"
270-
m_memory.erase(name);
267+
m_state.memory.erase(name);
271268
// assignment to slot contents denoted by "name"
272-
cxx20::erase_if(m_memory, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; }));
269+
cxx20::erase_if(m_state.memory, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; }));
273270
}
274271
}
275272

@@ -282,9 +279,9 @@ void DataFlowAnalyzer::handleAssignment(set<YulString> const& _variables, Expres
282279
// On the other hand, if we knew the value in the slot
283280
// already, then the sload() / mload() would have been replaced by a variable anyway.
284281
if (auto key = isSimpleLoad(StoreLoadLocation::Memory, *_value))
285-
m_memory[*key] = variable;
282+
m_state.memory[*key] = variable;
286283
else if (auto key = isSimpleLoad(StoreLoadLocation::Storage, *_value))
287-
m_storage[*key] = variable;
284+
m_state.storage[*key] = variable;
288285
}
289286
}
290287
}
@@ -298,8 +295,8 @@ void DataFlowAnalyzer::popScope()
298295
{
299296
for (auto const& name: m_variableScopes.back().variables)
300297
{
301-
m_value.erase(name);
302-
m_references.erase(name);
298+
m_state.value.erase(name);
299+
m_state.references.erase(name);
303300
}
304301
m_variableScopes.pop_back();
305302
}
@@ -325,53 +322,53 @@ void DataFlowAnalyzer::clearValues(set<YulString> _variables)
325322
auto eraseCondition = mapTuple([&_variables](auto&& key, auto&& value) {
326323
return _variables.count(key) || _variables.count(value);
327324
});
328-
cxx20::erase_if(m_storage, eraseCondition);
329-
cxx20::erase_if(m_memory, eraseCondition);
325+
cxx20::erase_if(m_state.storage, eraseCondition);
326+
cxx20::erase_if(m_state.memory, eraseCondition);
330327

331328
// Also clear variables that reference variables to be cleared.
332329
for (auto const& variableToClear: _variables)
333-
for (auto const& [ref, names]: m_references)
330+
for (auto const& [ref, names]: m_state.references)
334331
if (names.count(variableToClear))
335332
_variables.emplace(ref);
336333

337334
// Clear the value and update the reference relation.
338335
for (auto const& name: _variables)
339336
{
340-
m_value.erase(name);
341-
m_references.erase(name);
337+
m_state.value.erase(name);
338+
m_state.references.erase(name);
342339
}
343340
}
344341

345342
void DataFlowAnalyzer::assignValue(YulString _variable, Expression const* _value)
346343
{
347-
m_value[_variable] = {_value, m_loopDepth};
344+
m_state.value[_variable] = {_value, m_loopDepth};
348345
}
349346

350347
void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Block const& _block)
351348
{
352349
SideEffectsCollector sideEffects(m_dialect, _block, &m_functionSideEffects);
353350
if (sideEffects.invalidatesStorage())
354-
m_storage.clear();
351+
m_state.storage.clear();
355352
if (sideEffects.invalidatesMemory())
356-
m_memory.clear();
353+
m_state.memory.clear();
357354
}
358355

359356
void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Expression const& _expr)
360357
{
361358
SideEffectsCollector sideEffects(m_dialect, _expr, &m_functionSideEffects);
362359
if (sideEffects.invalidatesStorage())
363-
m_storage.clear();
360+
m_state.storage.clear();
364361
if (sideEffects.invalidatesMemory())
365-
m_memory.clear();
362+
m_state.memory.clear();
366363
}
367364

368365
void DataFlowAnalyzer::joinKnowledge(
369366
unordered_map<YulString, YulString> const& _olderStorage,
370367
unordered_map<YulString, YulString> const& _olderMemory
371368
)
372369
{
373-
joinKnowledgeHelper(m_storage, _olderStorage);
374-
joinKnowledgeHelper(m_memory, _olderMemory);
370+
joinKnowledgeHelper(m_state.storage, _olderStorage);
371+
joinKnowledgeHelper(m_state.memory, _olderMemory);
375372
}
376373

377374
void DataFlowAnalyzer::joinKnowledgeHelper(
@@ -381,8 +378,8 @@ void DataFlowAnalyzer::joinKnowledgeHelper(
381378
{
382379
// We clear if the key does not exist in the older map or if the value is different.
383380
// This also works for memory because _older is an "older version"
384-
// of m_memory and thus any overlapping write would have cleared the keys
385-
// that are not known to be different inside m_memory already.
381+
// of m_state.memory and thus any overlapping write would have cleared the keys
382+
// that are not known to be different inside m_state.memory already.
386383
cxx20::erase_if(_this, mapTuple([&_older](auto&& key, auto&& currentValue){
387384
YulString const* oldValue = util::valueOrNullptr(_older, key);
388385
return !oldValue || *oldValue != currentValue;
@@ -433,4 +430,3 @@ std::optional<YulString> DataFlowAnalyzer::isSimpleLoad(
433430
return key->name;
434431
return {};
435432
}
436-

libyul/optimiser/DataFlowAnalyzer.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ class DataFlowAnalyzer: public ASTModifier
101101
void operator()(Block& _block) override;
102102

103103
/// @returns the current value of the given variable, if known - always movable.
104-
AssignedValue const* variableValue(YulString _variable) const { return util::valueOrNullptr(m_value, _variable); }
105-
std::set<YulString> const* references(YulString _variable) const { return util::valueOrNullptr(m_references, _variable); }
106-
std::map<YulString, AssignedValue> const& allValues() const { return m_value; }
104+
AssignedValue const* variableValue(YulString _variable) const { return util::valueOrNullptr(m_state.value, _variable); }
105+
std::set<YulString> const* references(YulString _variable) const { return util::valueOrNullptr(m_state.references, _variable); }
106+
std::map<YulString, AssignedValue> const& allValues() const { return m_state.value; }
107107
std::optional<YulString> storageValue(YulString _key) const;
108108
std::optional<YulString> memoryValue(YulString _key) const;
109109

@@ -173,14 +173,20 @@ class DataFlowAnalyzer: public ASTModifier
173173
/// if this is not provided or the function is not found.
174174
std::map<YulString, SideEffects> m_functionSideEffects;
175175

176-
/// Current values of variables, always movable.
177-
std::map<YulString, AssignedValue> m_value;
178-
/// m_references[a].contains(b) <=> the current expression assigned to a references b
179-
std::unordered_map<YulString, std::set<YulString>> m_references;
176+
private:
177+
struct State
178+
{
179+
/// Current values of variables, always movable.
180+
std::map<YulString, AssignedValue> value;
181+
/// m_references[a].contains(b) <=> the current expression assigned to a references b
182+
std::unordered_map<YulString, std::set<YulString>> references;
180183

181-
std::unordered_map<YulString, YulString> m_storage;
182-
std::unordered_map<YulString, YulString> m_memory;
184+
std::unordered_map<YulString, YulString> storage;
185+
std::unordered_map<YulString, YulString> memory;
186+
};
187+
State m_state;
183188

189+
protected:
184190
KnowledgeBase m_knowledgeBase;
185191

186192
YulString m_storeFunctionName[static_cast<unsigned>(StoreLoadLocation::Last) + 1];

0 commit comments

Comments
 (0)