Coverage Report

Created: 2025-06-24 07:59

/src/solidity/libyul/optimiser/DeadCodeEliminator.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 unreachable code.
20
 */
21
22
#include <libyul/optimiser/DeadCodeEliminator.h>
23
#include <libyul/optimiser/Semantics.h>
24
#include <libyul/optimiser/OptimiserStep.h>
25
#include <libyul/ControlFlowSideEffectsCollector.h>
26
#include <libyul/AST.h>
27
28
#include <libevmasm/SemanticInformation.h>
29
30
#include <algorithm>
31
#include <limits>
32
33
using namespace solidity;
34
using namespace solidity::util;
35
using namespace solidity::yul;
36
37
void DeadCodeEliminator::run(OptimiserStepContext& _context, Block& _ast)
38
311k
{
39
311k
  ControlFlowSideEffectsCollector sideEffects(_context.dialect, _ast);
40
311k
  DeadCodeEliminator{
41
311k
    _context.dialect,
42
311k
    sideEffects.functionSideEffectsNamed()
43
311k
  }(_ast);
44
311k
}
45
46
void DeadCodeEliminator::operator()(ForLoop& _for)
47
845k
{
48
845k
  yulAssert(_for.pre.statements.empty(), "DeadCodeEliminator needs ForLoopInitRewriter as a prerequisite.");
49
845k
  ASTModifier::operator()(_for);
50
845k
}
51
52
void DeadCodeEliminator::operator()(Block& _block)
53
5.20M
{
54
5.20M
  TerminationFinder::ControlFlow controlFlowChange;
55
5.20M
  size_t index;
56
5.20M
  std::tie(controlFlowChange, index) = TerminationFinder{m_dialect, &m_functionSideEffects}.firstUnconditionalControlFlowChange(_block.statements);
57
58
  // Erase everything after the terminating statement that is not a function definition.
59
5.20M
  if (controlFlowChange != TerminationFinder::ControlFlow::FlowOut && index != std::numeric_limits<size_t>::max())
60
835k
    _block.statements.erase(
61
835k
      remove_if(
62
835k
        _block.statements.begin() + static_cast<ptrdiff_t>(index) + 1,
63
835k
        _block.statements.end(),
64
835k
        [] (Statement const& _s) { return !std::holds_alternative<yul::FunctionDefinition>(_s); }
65
835k
      ),
66
835k
      _block.statements.end()
67
835k
    );
68
69
5.20M
  ASTModifier::operator()(_block);
70
5.20M
}