Coverage Report

Created: 2022-08-24 06:43

/src/solidity/libyul/optimiser/ExpressionInliner.cpp
Line
Count
Source (jump to first uncovered line)
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
 * Optimiser component that performs function inlining inside expressions.
20
 */
21
22
#include <libyul/optimiser/ExpressionInliner.h>
23
24
#include <libyul/optimiser/InlinableExpressionFunctionFinder.h>
25
#include <libyul/optimiser/Metrics.h>
26
#include <libyul/optimiser/NameCollector.h>
27
#include <libyul/optimiser/Substitution.h>
28
#include <libyul/optimiser/Semantics.h>
29
#include <libyul/optimiser/OptimiserStep.h>
30
31
#include <libyul/AST.h>
32
33
using namespace std;
34
using namespace solidity;
35
using namespace solidity::yul;
36
37
void ExpressionInliner::run(OptimiserStepContext& _context, Block& _ast)
38
12.9k
{
39
12.9k
  InlinableExpressionFunctionFinder funFinder;
40
12.9k
  funFinder(_ast);
41
12.9k
  ExpressionInliner inliner{_context.dialect, funFinder.inlinableFunctions()};
42
12.9k
  inliner(_ast);
43
12.9k
}
44
45
void ExpressionInliner::operator()(FunctionDefinition& _fun)
46
125k
{
47
125k
  ASTModifier::operator()(_fun);
48
125k
}
49
50
void ExpressionInliner::visit(Expression& _expression)
51
2.25M
{
52
2.25M
  ASTModifier::visit(_expression);
53
2.25M
  if (holds_alternative<FunctionCall>(_expression))
54
942k
  {
55
942k
    FunctionCall& funCall = std::get<FunctionCall>(_expression);
56
942k
    if (!m_inlinableFunctions.count(funCall.functionName.name))
57
865k
      return;
58
76.9k
    FunctionDefinition const& fun = *m_inlinableFunctions.at(funCall.functionName.name);
59
60
76.9k
    map<YulString, Expression const*> substitutions;
61
143k
    for (size_t i = 0; i < funCall.arguments.size(); i++)
62
71.6k
    {
63
71.6k
      Expression const& arg = funCall.arguments[i];
64
71.6k
      YulString paraName = fun.parameters[i].name;
65
66
71.6k
      if (!SideEffectsCollector(m_dialect, arg).movable())
67
5.47k
        return;
68
69
66.2k
      size_t refs = ReferencesCounter::countReferences(fun.body)[paraName];
70
66.2k
      size_t cost = CodeCost::codeCost(m_dialect, arg);
71
72
66.2k
      if (refs > 1 && cost > 1)
73
0
        return;
74
75
66.2k
      substitutions[paraName] = &arg;
76
66.2k
    }
77
78
71.4k
    _expression = Substitution(substitutions).translate(*std::get<Assignment>(fun.body.statements.front()).value);
79
71.4k
  }
80
2.25M
}