Coverage Report

Created: 2026-08-14 07:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/solidity/libyul/optimiser/EqualStoreEliminator.cpp
Line
Count
Source
1
/*
2
  This file is part of solidity.
3
4
  solidity is free software: you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
9
  solidity is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
// SPDX-License-Identifier: GPL-3.0
18
/**
19
 * Optimisation stage that removes mstore and sstore operations if they store the same
20
 * value that is already known to be in that slot.
21
 */
22
23
#include <libyul/optimiser/EqualStoreEliminator.h>
24
25
#include <libyul/optimiser/CallGraphGenerator.h>
26
#include <libyul/optimiser/OptimizerUtilities.h>
27
#include <libyul/optimiser/Semantics.h>
28
#include <libyul/AST.h>
29
#include <libyul/Utilities.h>
30
31
using namespace solidity;
32
using namespace solidity::util;
33
using namespace solidity::evmasm;
34
using namespace solidity::yul;
35
36
void EqualStoreEliminator::run(OptimiserStepContext const& _context, Block& _ast)
37
104k
{
38
104k
  EqualStoreEliminator eliminator{
39
104k
    _context.dialect,
40
104k
    SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast))
41
104k
  };
42
104k
  eliminator(_ast);
43
44
104k
  StatementRemover remover{eliminator.m_pendingRemovals};
45
104k
  remover(_ast);
46
104k
}
47
48
void EqualStoreEliminator::visit(Statement& _statement)
49
5.48M
{
50
  // No need to consider potential changes through complex arguments since
51
  // isSimpleStore only returns something if the arguments are identifiers.
52
5.48M
  if (ExpressionStatement const* expression = std::get_if<ExpressionStatement>(&_statement))
53
835k
  {
54
835k
    if (auto vars = isSimpleStore(StoreLoadLocation::Storage, *expression))
55
278k
    {
56
278k
      if (std::optional<YulName> currentValue = storageValue(vars->first))
57
1.67k
        if (*currentValue == vars->second)
58
188
          m_pendingRemovals.insert(&_statement);
59
278k
    }
60
556k
    else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, *expression))
61
124k
    {
62
124k
      if (std::optional<YulName> currentValue = memoryValue(vars->first))
63
37
        if (*currentValue == vars->second)
64
23
          m_pendingRemovals.insert(&_statement);
65
124k
    }
66
835k
  }
67
68
5.48M
  DataFlowAnalyzer::visit(_statement);
69
5.48M
}