Use erase-remove idiom to remove dead SkSL functions.

This pattern is a bit more efficient when multiple removals occur; it
avoids moving elements up more than once.
(https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom)

Change-Id: I612d3c52145c889e30f7203f3c7298e461e855a5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/314459
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index e41a187..64988a2 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -1641,25 +1641,32 @@
         program.fIsOptimized = true;
         fIRGenerator->fKind = program.fKind;
         fIRGenerator->fSettings = &program.fSettings;
-        for (auto& element : program) {
+
+        // Build the control-flow graph for each function.
+        for (ProgramElement& element : program) {
             if (element.fKind == ProgramElement::kFunction_Kind) {
                 this->scanCFG(element.as<FunctionDefinition>());
             }
         }
-        // we wait until after analysis to remove dead functions so that we still report errors
-        // even in unused code
+
+        // Remove dead functions. We wait until after analysis so that we still report errors, even
+        // in unused code.
         if (program.fSettings.fRemoveDeadFunctions) {
-            for (auto iter = program.fElements.begin(); iter != program.fElements.end(); ) {
-                if ((*iter)->fKind == ProgramElement::kFunction_Kind) {
-                    const FunctionDefinition& f = (*iter)->as<FunctionDefinition>();
-                    if (!f.fDeclaration.fCallCount && f.fDeclaration.fName != "main") {
-                        iter = program.fElements.erase(iter);
-                        continue;
-                    }
-                }
-                ++iter;
-            }
+            program.fElements.erase(
+                    std::remove_if(program.fElements.begin(),
+                                   program.fElements.end(),
+                                   [](const std::unique_ptr<ProgramElement>& pe) {
+                                       if (pe->fKind != ProgramElement::kFunction_Kind) {
+                                           return false;
+                                       }
+                                       const FunctionDefinition& fn = pe->as<FunctionDefinition>();
+                                       return fn.fDeclaration.fCallCount == 0 &&
+                                              fn.fDeclaration.fName != "main";
+                                   }),
+                    program.fElements.end());
         }
+
+        // Remove dead variables.
         if (program.fKind != Program::kFragmentProcessor_Kind) {
             for (auto iter = program.fElements.begin(); iter != program.fElements.end();) {
                 if ((*iter)->fKind == ProgramElement::kVar_Kind) {