1 /*
2 * Copyright 2021 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/sksl/SkSLContext.h"
9 #include "src/sksl/SkSLModule.h"
10 #include "src/sksl/SkSLProgramSettings.h"
11 #include "src/sksl/analysis/SkSLProgramUsage.h"
12 #include "src/sksl/ir/SkSLFunctionDeclaration.h"
13 #include "src/sksl/ir/SkSLFunctionDefinition.h"
14 #include "src/sksl/ir/SkSLProgram.h"
15 #include "src/sksl/ir/SkSLProgramElement.h"
16 #include "src/sksl/transform/SkSLTransform.h"
17
18 #include <algorithm>
19 #include <cstddef>
20 #include <memory>
21 #include <vector>
22
23 namespace SkSL {
24
dead_function_predicate(const ProgramElement * element,ProgramUsage * usage)25 static bool dead_function_predicate(const ProgramElement* element, ProgramUsage* usage) {
26 if (!element->is<FunctionDefinition>()) {
27 return false;
28 }
29 const FunctionDefinition& fn = element->as<FunctionDefinition>();
30 if (fn.declaration().isMain() || usage->get(fn.declaration()) > 0) {
31 return false;
32 }
33 // This function is about to be eliminated by remove_if; update ProgramUsage accordingly.
34 usage->remove(*element);
35 return true;
36 }
37
EliminateDeadFunctions(Program & program)38 bool Transform::EliminateDeadFunctions(Program& program) {
39 ProgramUsage* usage = program.fUsage.get();
40
41 size_t numOwnedElements = program.fOwnedElements.size();
42 size_t numSharedElements = program.fSharedElements.size();
43
44 if (program.fConfig->fSettings.fRemoveDeadFunctions) {
45 program.fOwnedElements.erase(std::remove_if(program.fOwnedElements.begin(),
46 program.fOwnedElements.end(),
47 [&](const std::unique_ptr<ProgramElement>& pe) {
48 return dead_function_predicate(pe.get(),
49 usage);
50 }),
51 program.fOwnedElements.end());
52 program.fSharedElements.erase(std::remove_if(program.fSharedElements.begin(),
53 program.fSharedElements.end(),
54 [&](const ProgramElement* pe) {
55 return dead_function_predicate(pe, usage);
56 }),
57 program.fSharedElements.end());
58 }
59 return program.fOwnedElements.size() < numOwnedElements ||
60 program.fSharedElements.size() < numSharedElements;
61 }
62
EliminateDeadFunctions(const Context & context,Module & module,ProgramUsage * usage)63 bool Transform::EliminateDeadFunctions(const Context& context,
64 Module& module,
65 ProgramUsage* usage) {
66 size_t numElements = module.fElements.size();
67
68 if (context.fConfig->fSettings.fRemoveDeadFunctions) {
69 module.fElements.erase(std::remove_if(module.fElements.begin(),
70 module.fElements.end(),
71 [&](const std::unique_ptr<ProgramElement>& pe) {
72 return dead_function_predicate(pe.get(), usage);
73 }),
74 module.fElements.end());
75 }
76 return module.fElements.size() < numElements;
77 }
78
79 } // namespace SkSL
80