| /* |
| * Copyright 2021 Google LLC |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "src/base/SkStringView.h" |
| #include "src/sksl/SkSLCompiler.h" |
| #include "src/sksl/SkSLContext.h" |
| #include "src/sksl/SkSLProgramSettings.h" |
| #include "src/sksl/analysis/SkSLProgramUsage.h" |
| #include "src/sksl/ir/SkSLProgram.h" |
| #include "src/sksl/ir/SkSLProgramElement.h" |
| #include "src/sksl/ir/SkSLVarDeclarations.h" |
| #include "src/sksl/ir/SkSLVariable.h" |
| #include "src/sksl/transform/SkSLTransform.h" |
| |
| #include <algorithm> |
| #include <cstddef> |
| #include <memory> |
| #include <vector> |
| |
| namespace SkSL { |
| |
| static bool is_dead_variable(const ProgramElement& element, |
| ProgramUsage* usage, |
| bool onlyPrivateGlobals) { |
| if (!element.is<GlobalVarDeclaration>()) { |
| return false; |
| } |
| const GlobalVarDeclaration& global = element.as<GlobalVarDeclaration>(); |
| const VarDeclaration& varDecl = global.varDeclaration(); |
| if (onlyPrivateGlobals && !skstd::starts_with(varDecl.var()->name(), '$')) { |
| return false; |
| } |
| if (!usage->isDead(*varDecl.var())) { |
| return false; |
| } |
| // This declaration is about to be eliminated by remove_if; update ProgramUsage accordingly. |
| usage->remove(&varDecl); |
| return true; |
| } |
| |
| bool Transform::EliminateDeadGlobalVariables(const Context& context, |
| Module& module, |
| ProgramUsage* usage, |
| bool onlyPrivateGlobals) { |
| auto isDeadVariable = [&](const ProgramElement& element) { |
| return is_dead_variable(element, usage, onlyPrivateGlobals); |
| }; |
| |
| size_t numElements = module.fElements.size(); |
| if (context.fConfig->fSettings.fRemoveDeadVariables) { |
| module.fElements.erase(std::remove_if(module.fElements.begin(), |
| module.fElements.end(), |
| [&](const std::unique_ptr<ProgramElement>& pe) { |
| return isDeadVariable(*pe); |
| }), |
| module.fElements.end()); |
| } |
| return module.fElements.size() < numElements; |
| } |
| |
| bool Transform::EliminateDeadGlobalVariables(Program& program) { |
| auto isDeadVariable = [&](const ProgramElement& element) { |
| return is_dead_variable(element, program.fUsage.get(), /*onlyPrivateGlobals=*/false); |
| }; |
| |
| size_t numOwnedElements = program.fOwnedElements.size(); |
| size_t numSharedElements = program.fSharedElements.size(); |
| if (program.fConfig->fSettings.fRemoveDeadVariables) { |
| program.fOwnedElements.erase(std::remove_if(program.fOwnedElements.begin(), |
| program.fOwnedElements.end(), |
| [&](const std::unique_ptr<ProgramElement>& pe) { |
| return isDeadVariable(*pe); |
| }), |
| program.fOwnedElements.end()); |
| program.fSharedElements.erase(std::remove_if(program.fSharedElements.begin(), |
| program.fSharedElements.end(), |
| [&](const ProgramElement* pe) { |
| return isDeadVariable(*pe); |
| }), |
| program.fSharedElements.end()); |
| } |
| return program.fOwnedElements.size() < numOwnedElements || |
| program.fSharedElements.size() < numSharedElements; |
| } |
| |
| } // namespace SkSL |