/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. solidity is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with solidity. If not, see . */ // SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that removes stores to memory and storage slots that are not used * or overwritten later on. */ #pragma once #include #include #include #include #include #include #include #include namespace solidity::yul { struct Dialect; struct AssignedValue; /** * Optimizer component that removes sstore statements if they * are overwritten in all code paths or never read from. * * The m_store member of UnusedStoreBase is only used with the empty yul string * as key in the first dimension. * * Best run in SSA form. * * Prerequisite: Disambiguator, ForLoopInitRewriter. */ class UnusedStoreEliminator: public UnusedStoreBase { public: static constexpr char const* name{"UnusedStoreEliminator"}; static void run(OptimiserStepContext& _context, Block& _ast); explicit UnusedStoreEliminator( Dialect const& _dialect, std::map const& _functionSideEffects, std::map _controlFlowSideEffects, std::map const& _ssaValues, bool _ignoreMemory ): UnusedStoreBase(_dialect), m_ignoreMemory(_ignoreMemory), m_functionSideEffects(_functionSideEffects), m_controlFlowSideEffects(_controlFlowSideEffects), m_ssaValues(_ssaValues) {} using UnusedStoreBase::operator(); void operator()(FunctionCall const& _functionCall) override; void operator()(FunctionDefinition const&) override; void operator()(Leave const&) override; using UnusedStoreBase::visit; void visit(Statement const& _statement) override; using Location = evmasm::SemanticInformation::Location; using Effect = evmasm::SemanticInformation::Effect; struct Operation { Location location; Effect effect; /// Start of affected area. Unknown if not provided. std::optional start; /// Length of affected area, unknown if not provided. /// Unused for storage. std::optional length; }; private: void shortcutNestedLoop(TrackedStores const&) override { // We might only need to do this for newly introduced stores in the loop. changeUndecidedTo(State::Used); } void finalizeFunctionDefinition(FunctionDefinition const&) override; std::vector operationsFromFunctionCall(FunctionCall const& _functionCall) const; void applyOperation(Operation const& _operation); bool knownUnrelated(Operation const& _op1, Operation const& _op2) const; bool knownCovered(Operation const& _covered, Operation const& _covering) const; void changeUndecidedTo(State _newState, std::optional _onlyLocation = std::nullopt); void scheduleUnusedForDeletion(); std::optional identifierNameIfSSA(Expression const& _expression) const; bool const m_ignoreMemory; std::map const& m_functionSideEffects; std::map m_controlFlowSideEffects; std::map const& m_ssaValues; std::map m_storeOperations; }; }