Coverage Report

Created: 2025-09-08 08:10

/src/solidity/libyul/optimiser/ConditionalSimplifier.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
#include <libyul/optimiser/ConditionalSimplifier.h>
19
#include <libyul/optimiser/Semantics.h>
20
#include <libyul/AST.h>
21
#include <libyul/optimiser/NameCollector.h>
22
#include <libyul/ControlFlowSideEffectsCollector.h>
23
#include <libsolutil/CommonData.h>
24
25
using namespace solidity;
26
using namespace solidity::yul;
27
using namespace solidity::util;
28
29
void ConditionalSimplifier::run(OptimiserStepContext& _context, Block& _ast)
30
244k
{
31
244k
  ConditionalSimplifier{
32
244k
    _context.dialect,
33
244k
    ControlFlowSideEffectsCollector{_context.dialect, _ast}.functionSideEffectsNamed()
34
244k
  }(_ast);
35
244k
}
36
37
void ConditionalSimplifier::operator()(Switch& _switch)
38
251k
{
39
251k
  visit(*_switch.expression);
40
251k
  if (!std::holds_alternative<Identifier>(*_switch.expression))
41
101
  {
42
101
    ASTModifier::operator()(_switch);
43
101
    return;
44
101
  }
45
250k
  YulName expr = std::get<Identifier>(*_switch.expression).name;
46
250k
  for (auto& _case: _switch.cases)
47
730k
  {
48
730k
    if (_case.value)
49
548k
    {
50
548k
      (*this)(*_case.value);
51
548k
      _case.body.statements.insert(_case.body.statements.begin(),
52
548k
        Assignment{
53
548k
          _case.body.debugData,
54
548k
          {Identifier{_case.body.debugData, expr}},
55
548k
          std::make_unique<Expression>(*_case.value)
56
548k
        }
57
548k
      );
58
548k
    }
59
730k
    (*this)(_case.body);
60
730k
  }
61
250k
}
62
63
void ConditionalSimplifier::operator()(Block& _block)
64
4.91M
{
65
4.91M
  iterateReplacing(
66
4.91M
    _block.statements,
67
4.91M
    [&](Statement& _s) -> std::optional<std::vector<Statement>>
68
42.4M
    {
69
42.4M
      visit(_s);
70
42.4M
      if (std::holds_alternative<If>(_s))
71
658k
      {
72
658k
        If& _if = std::get<If>(_s);
73
658k
        if (
74
658k
          std::holds_alternative<Identifier>(*_if.condition) &&
75
658k
          !_if.body.statements.empty() &&
76
658k
          TerminationFinder(m_dialect, &m_functionSideEffects).controlFlowKind(_if.body.statements.back()) !=
77
646k
            TerminationFinder::ControlFlow::FlowOut
78
658k
        )
79
529k
        {
80
529k
          YulName condition = std::get<Identifier>(*_if.condition).name;
81
529k
          langutil::DebugData::ConstPtr debugData = _if.debugData;
82
529k
          return make_vector<Statement>(
83
529k
            std::move(_s),
84
529k
            Assignment{
85
529k
              debugData,
86
529k
              {Identifier{debugData, condition}},
87
529k
              std::make_unique<Expression>(m_dialect.zeroLiteral())
88
529k
            }
89
529k
          );
90
529k
        }
91
658k
      }
92
41.9M
      return {};
93
42.4M
    }
94
4.91M
  );
95
4.91M
}