Run the optimizer until we stop finding improvements.

This will be especially important once more aggressive inlining is
enabled, as the optimizer will need to run dead-function elimination
passes after inlining.

Change-Id: I8ccd5d6a9a041ee2b0a3ec5ef305e5df875b6947
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/315738
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2020-09-09 13:40:37 -04:00 committed by Skia Commit-Bot
parent 9fd0394c3a
commit 73a6bff204
2 changed files with 64 additions and 48 deletions

View File

@ -1650,51 +1650,68 @@ bool Compiler::optimize(Program& program) {
fIRGenerator->fSettings = &program.fSettings;
// Scan and optimize based on the control-flow graph for each function.
for (ProgramElement& element : program) {
if (element.kind() == ProgramElement::Kind::kFunction) {
this->scanCFG(element.as<FunctionDefinition>());
}
}
while (fErrorCount == 0) {
bool madeChanges = false;
// Remove dead functions. We wait until after analysis so that we still report errors, even
// in unused code.
if (program.fSettings.fRemoveDeadFunctions) {
program.fElements.erase(
std::remove_if(program.fElements.begin(),
program.fElements.end(),
[](const std::unique_ptr<ProgramElement>& pe) {
if (pe->kind() != ProgramElement::Kind::kFunction) {
return false;
}
const FunctionDefinition& fn = pe->as<FunctionDefinition>();
return fn.fDeclaration.fCallCount == 0 &&
fn.fDeclaration.fName != "main";
}),
program.fElements.end());
}
if (program.fKind != Program::kFragmentProcessor_Kind) {
// Remove dead variables.
for (ProgramElement& element : program) {
if (element.kind() == ProgramElement::Kind::kVar) {
VarDeclarations& vars = element.as<VarDeclarations>();
vars.fVars.erase(
std::remove_if(vars.fVars.begin(), vars.fVars.end(),
[](const std::unique_ptr<Statement>& stmt) {
return stmt->as<VarDeclaration>().fVar->dead();
}),
vars.fVars.end());
if (element.is<FunctionDefinition>()) {
madeChanges |= this->scanCFG(element.as<FunctionDefinition>());
}
}
// Remove empty variable declarations with no variables left inside of them.
program.fElements.erase(
std::remove_if(program.fElements.begin(), program.fElements.end(),
[](const std::unique_ptr<ProgramElement>& element) {
return element->kind() == ProgramElement::Kind::kVar &&
element->as<VarDeclarations>().fVars.empty();
}),
program.fElements.end());
// Remove dead functions. We wait until after analysis so that we still report errors,
// even in unused code.
if (program.fSettings.fRemoveDeadFunctions) {
program.fElements.erase(
std::remove_if(program.fElements.begin(),
program.fElements.end(),
[&](const std::unique_ptr<ProgramElement>& element) {
if (!element->is<FunctionDefinition>()) {
return false;
}
const auto& fn = element->as<FunctionDefinition>();
bool dead = fn.fDeclaration.fCallCount == 0 &&
fn.fDeclaration.fName != "main";
madeChanges |= dead;
return dead;
}),
program.fElements.end());
}
if (program.fKind != Program::kFragmentProcessor_Kind) {
// Remove dead variables.
for (ProgramElement& element : program) {
if (!element.is<VarDeclarations>()) {
continue;
}
VarDeclarations& vars = element.as<VarDeclarations>();
vars.fVars.erase(
std::remove_if(vars.fVars.begin(), vars.fVars.end(),
[&](const std::unique_ptr<Statement>& stmt) {
bool dead = stmt->as<VarDeclaration>().fVar->dead();
madeChanges |= dead;
return dead;
}),
vars.fVars.end());
}
// Remove empty variable declarations with no variables left inside of them.
program.fElements.erase(
std::remove_if(program.fElements.begin(), program.fElements.end(),
[&](const std::unique_ptr<ProgramElement>& element) {
if (!element->is<VarDeclarations>()) {
return false;
}
bool dead = element->as<VarDeclarations>().fVars.empty();
madeChanges |= dead;
return dead;
}),
program.fElements.end());
}
if (!madeChanges) {
break;
}
}
}
return fErrorCount == 0;

View File

@ -2653,12 +2653,11 @@ DEF_TEST(SkSLDiscard, r) {
" sk_FragColor = half4(x);"
"}",
*SkSL::ShaderCapsFactory::Default(),
"#version 400\n"
"void main() {\n"
" float x;\n"
" {\n"
" x = 1.0;\n"
" discard;\n"
" }\n"
"}\n");
R"__GLSL__(#version 400
void main() {
{
discard;
}
}
)__GLSL__");
}