mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
unused store
This commit is contained in:
parent
ddbcea047b
commit
b09a8c62bb
@ -50,7 +50,7 @@ static string const one{"@ 1"};
|
||||
static string const thirtyTwo{"@ 32"};
|
||||
|
||||
|
||||
void UnusedStoreEliminator::run(OptimiserStepContext& /*_context*/, Block& /*_ast*/)
|
||||
void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast)
|
||||
{
|
||||
map<YulString, SideEffects> functionSideEffects = SideEffectsPropagator::sideEffects(
|
||||
_context.dialect,
|
||||
@ -87,9 +87,8 @@ void UnusedStoreEliminator::run(OptimiserStepContext& /*_context*/, Block& /*_as
|
||||
else
|
||||
rse.markActiveAsUsed(Location::Memory);
|
||||
rse.markActiveAsUsed(Location::Storage);
|
||||
rse.scheduleUnusedForDeletion();
|
||||
|
||||
StatementRemover remover(rse.m_pendingRemovals);
|
||||
StatementRemover remover{rse.m_allStores - rse.m_usedStores};
|
||||
remover(_ast);
|
||||
}
|
||||
|
||||
@ -192,9 +191,9 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
|
||||
vector<Operation> operations = operationsFromFunctionCall(*funCall);
|
||||
yulAssert(operations.size() == 1, "");
|
||||
if (operations.front().location == Location::Storage)
|
||||
m_activeStores["s"_yulstring].insert(&_statement);
|
||||
activeStorageStores().insert(&_statement);
|
||||
else
|
||||
m_activeStores["m"_yulstring].insert(&_statement);
|
||||
activeMemoryStores().insert(&_statement);
|
||||
m_storeOperations[&_statement] = std::move(operations.front());
|
||||
}
|
||||
}
|
||||
@ -202,7 +201,6 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
|
||||
void UnusedStoreEliminator::finalizeFunctionDefinition(FunctionDefinition const&)
|
||||
{
|
||||
markActiveAsUsed();
|
||||
scheduleUnusedForDeletion();
|
||||
}
|
||||
|
||||
vector<UnusedStoreEliminator::Operation> UnusedStoreEliminator::operationsFromFunctionCall(
|
||||
@ -257,31 +255,27 @@ vector<UnusedStoreEliminator::Operation> UnusedStoreEliminator::operationsFromFu
|
||||
|
||||
void UnusedStoreEliminator::applyOperation(UnusedStoreEliminator::Operation const& _operation)
|
||||
{
|
||||
// TODO only one will be relevant, depending on _operation.location
|
||||
for (Statement const* statement: m_activeStores["s"_yulstring])
|
||||
set<Statement const*> toRemove;
|
||||
set<Statement const*>& active =
|
||||
_operation.location == Location::Storage ?
|
||||
activeStorageStores() :
|
||||
activeMemoryStores();
|
||||
|
||||
// TODO this loop could be done more efficiently - removing while iterating.
|
||||
for (Statement const* statement: active)
|
||||
{
|
||||
Operation const& storeOperation = m_storeOperations.at(statement);
|
||||
if (_operation.effect == Effect::Read && !knownUnrelated(storeOperation, _operation))
|
||||
// TODO remove from active!
|
||||
m_usedStores.insert(statement);
|
||||
else if (_operation.effect == Effect::Write && knownCovered(storeOperation, _operation))
|
||||
{
|
||||
// TODO remove from active
|
||||
// state = State::Unused;
|
||||
}
|
||||
}
|
||||
for (Statement const* statement: m_activeStores["m"_yulstring])
|
||||
{
|
||||
Operation const& storeOperation = m_storeOperations.at(statement);
|
||||
if (_operation.effect == Effect::Read && !knownUnrelated(storeOperation, _operation))
|
||||
// TODO remove from active!
|
||||
// This store is read from, mark it as used and remove it from the active set.
|
||||
m_usedStores.insert(statement);
|
||||
else if (_operation.effect == Effect::Write && knownCovered(storeOperation, _operation))
|
||||
{
|
||||
// TODO remove from active
|
||||
// state = State::Unused;
|
||||
toRemove.insert(statement);
|
||||
}
|
||||
else if (_operation.effect == Effect::Write && knownCovered(storeOperation, _operation))
|
||||
// This store is overwritten before being read, remove it from the active set.
|
||||
toRemove.insert(statement);
|
||||
}
|
||||
active -= toRemove;
|
||||
}
|
||||
|
||||
bool UnusedStoreEliminator::knownUnrelated(
|
||||
@ -403,26 +397,26 @@ bool UnusedStoreEliminator::knownCovered(
|
||||
}
|
||||
|
||||
void UnusedStoreEliminator::markActiveAsUsed(
|
||||
optional<UnusedStoreEliminator::Location> _onlyLocation)
|
||||
optional<UnusedStoreEliminator::Location> _onlyLocation
|
||||
)
|
||||
{
|
||||
// TODO it might make sense to use YulString{"m"} and YulString{"s"} for memory and storage.
|
||||
// BUT: Could be both!
|
||||
for (Statement const* statement: m_activeStores[YulString{}])
|
||||
if (_onlyLocation == nullopt || *_onlyLocation == m_storeOperations.at(statement).location)
|
||||
if (_onlyLocation == nullopt || _onlyLocation == Location::Memory)
|
||||
for (Statement const* statement: activeMemoryStores())
|
||||
m_usedStores.insert(statement);
|
||||
// TODO and remove from active
|
||||
if (_onlyLocation == nullopt || _onlyLocation == Location::Storage)
|
||||
for (Statement const* statement: activeStorageStores())
|
||||
m_usedStores.insert(statement);
|
||||
clearActive(_onlyLocation);
|
||||
}
|
||||
|
||||
void UnusedStoreEliminator::changeUndecidedTo(
|
||||
State _newState,
|
||||
optional<UnusedStoreEliminator::Location> _onlyLocation)
|
||||
void UnusedStoreEliminator::clearActive(
|
||||
optional<UnusedStoreEliminator::Location> _onlyLocation
|
||||
)
|
||||
{
|
||||
for (auto& [statement, state]: m_activeStores[YulString{}])
|
||||
if (
|
||||
state == State::Undecided &&
|
||||
(_onlyLocation == nullopt || *_onlyLocation == m_storeOperations.at(statement).location)
|
||||
)
|
||||
state = _newState;
|
||||
if (_onlyLocation == nullopt || _onlyLocation == Location::Memory)
|
||||
activeMemoryStores() = {};
|
||||
if (_onlyLocation == nullopt || _onlyLocation == Location::Storage)
|
||||
activeStorageStores() = {};
|
||||
}
|
||||
|
||||
optional<YulString> UnusedStoreEliminator::identifierNameIfSSA(Expression const& _expression) const
|
||||
@ -432,10 +426,3 @@ optional<YulString> UnusedStoreEliminator::identifierNameIfSSA(Expression const&
|
||||
return {identifier->name};
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
void UnusedStoreEliminator::scheduleUnusedForDeletion()
|
||||
{
|
||||
for (auto const& [statement, state]: m_activeStores[YulString{}])
|
||||
if (state == State::Unused)
|
||||
m_pendingRemovals.insert(statement);
|
||||
}
|
||||
|
@ -49,8 +49,7 @@ struct AssignedValue;
|
||||
* to sstore, as we don't know whether the memory location will be read once we leave the function's scope,
|
||||
* so the statement will be removed only if all code code paths lead to a memory overwrite.
|
||||
*
|
||||
* The m_store member of UnusedStoreBase is only used with the empty yul string
|
||||
* as key in the first dimension.
|
||||
* The m_store member of UnusedStoreBase uses the key "m" for memory ond "s" for storage stores.
|
||||
*
|
||||
* Best run in SSA form.
|
||||
*
|
||||
@ -64,12 +63,12 @@ public:
|
||||
|
||||
explicit UnusedStoreEliminator(
|
||||
Dialect const& _dialect,
|
||||
std::map<YulString, SideEffects> const& ,//_functionSideEffects,
|
||||
std::map<YulString, ControlFlowSideEffects>,// _controlFlowSideEffects,
|
||||
std::map<YulString, AssignedValue> const&,// _ssaValues,
|
||||
bool// _ignoreMemory
|
||||
std::map<YulString, SideEffects> const& _functionSideEffects,
|
||||
std::map<YulString, ControlFlowSideEffects> _controlFlowSideEffects,
|
||||
std::map<YulString, AssignedValue> const& _ssaValues,
|
||||
bool _ignoreMemory
|
||||
):
|
||||
UnusedStoreBase(_dialect)//,
|
||||
UnusedStoreBase(_dialect),
|
||||
m_ignoreMemory(_ignoreMemory),
|
||||
m_functionSideEffects(_functionSideEffects),
|
||||
m_controlFlowSideEffects(_controlFlowSideEffects),
|
||||
@ -98,10 +97,13 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
std::set<Statement const*>& activeMemoryStores() { return m_activeStores["m"_yulstring]; }
|
||||
std::set<Statement const*>& activeStorageStores() { return m_activeStores["m"_yulstring]; }
|
||||
|
||||
void shortcutNestedLoop(ActiveStores const&) override
|
||||
{
|
||||
// We might only need to do this for newly introduced stores in the loop.
|
||||
changeUndecidedTo(State::Used);
|
||||
markActiveAsUsed();
|
||||
}
|
||||
void finalizeFunctionDefinition(FunctionDefinition const&) override;
|
||||
|
||||
@ -112,7 +114,6 @@ private:
|
||||
|
||||
void markActiveAsUsed(std::optional<Location> _onlyLocation = std::nullopt);
|
||||
void clearActive(std::optional<Location> _onlyLocation = std::nullopt);
|
||||
void scheduleUnusedForDeletion();
|
||||
|
||||
std::optional<YulString> identifierNameIfSSA(Expression const& _expression) const;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user