Coverage Report

Created: 2024-09-11 07:09

/src/spirv-tools/source/opt/inline_exhaustive_pass.cpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2017 The Khronos Group Inc.
2
// Copyright (c) 2017 Valve Corporation
3
// Copyright (c) 2017 LunarG Inc.
4
//
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
//
9
//     http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing, software
12
// distributed under the License is distributed on an "AS IS" BASIS,
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
// See the License for the specific language governing permissions and
15
// limitations under the License.
16
17
#include "source/opt/inline_exhaustive_pass.h"
18
19
#include <utility>
20
21
namespace spvtools {
22
namespace opt {
23
24
9.93k
Pass::Status InlineExhaustivePass::InlineExhaustive(Function* func) {
25
9.93k
  bool modified = false;
26
  // Using block iterators here because of block erasures and insertions.
27
255k
  for (auto bi = func->begin(); bi != func->end(); ++bi) {
28
1.63M
    for (auto ii = bi->begin(); ii != bi->end();) {
29
1.39M
      if (IsInlinableFunctionCall(&*ii)) {
30
        // Inline call.
31
12.8k
        std::vector<std::unique_ptr<BasicBlock>> newBlocks;
32
12.8k
        std::vector<std::unique_ptr<Instruction>> newVars;
33
12.8k
        if (!GenInlineCode(&newBlocks, &newVars, ii, bi)) {
34
0
          return Status::Failure;
35
0
        }
36
        // If call block is replaced with more than one block, point
37
        // succeeding phis at new last block.
38
12.8k
        if (newBlocks.size() > 1) UpdateSucceedingPhis(newBlocks);
39
        // Replace old calling block with new block(s).
40
41
12.8k
        bi = bi.Erase();
42
43
103k
        for (auto& bb : newBlocks) {
44
103k
          bb->SetParent(func);
45
103k
        }
46
12.8k
        bi = bi.InsertBefore(&newBlocks);
47
        // Insert new function variables.
48
12.8k
        if (newVars.size() > 0)
49
9.27k
          func->begin()->begin().InsertBefore(std::move(newVars));
50
        // Restart inlining at beginning of calling block.
51
12.8k
        ii = bi->begin();
52
12.8k
        modified = true;
53
1.37M
      } else {
54
1.37M
        ++ii;
55
1.37M
      }
56
1.39M
    }
57
245k
  }
58
9.93k
  return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange);
59
9.93k
}
60
61
10.7k
Pass::Status InlineExhaustivePass::ProcessImpl() {
62
10.7k
  Status status = Status::SuccessWithoutChange;
63
  // Attempt exhaustive inlining on each entry point function in module
64
10.7k
  ProcessFunction pfn = [&status, this](Function* fp) {
65
9.93k
    status = CombineStatus(status, InlineExhaustive(fp));
66
9.93k
    return false;
67
9.93k
  };
68
10.7k
  context()->ProcessReachableCallTree(pfn);
69
10.7k
  return status;
70
10.7k
}
71
72
21.1k
InlineExhaustivePass::InlineExhaustivePass() = default;
73
74
10.7k
Pass::Status InlineExhaustivePass::Process() {
75
10.7k
  InitializeInline();
76
10.7k
  return ProcessImpl();
77
10.7k
}
78
79
}  // namespace opt
80
}  // namespace spvtools