Directly compute call counts, rather than mutating state
This causes a ~4% regression on sksl_large, but some of that
can be bought back in two ways:
1) Removing (now unnecessary) cloning of program elements
2) Hoisting the new analysis passes, with (nontrivial)
logic to update/maintain the call counts as we edit IR.
Also, this fixes bugs where we were emitting functions that
had "calls" from no-longer called functions.
Bug: skia:10776
Change-Id: I4f8c29957be2e4233a883c9a1125f363b82ee40c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/327198
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp
index f0ef4d5..ce4e61e 100644
--- a/src/sksl/SkSLInliner.cpp
+++ b/src/sksl/SkSLInliner.cpp
@@ -1131,6 +1131,30 @@
}
}
+static bool multiple_calls_to(const Program& program, const FunctionDeclaration* fn) {
+ class MulitpleCallVisitor : public ProgramVisitor {
+ public:
+ MulitpleCallVisitor(const FunctionDeclaration* function) : fFunction(function) {}
+
+ bool visitExpression(const Expression& e) override {
+ if (e.is<FunctionCall>() && &e.as<FunctionCall>().function() == fFunction) {
+ if (fCalled) {
+ return true;
+ }
+ fCalled = true;
+ }
+ return INHERITED::visitExpression(e);
+ }
+
+ const FunctionDeclaration* fFunction;
+ bool fCalled = false;
+ using INHERITED = ProgramVisitor;
+ };
+
+ MulitpleCallVisitor visitor(fn);
+ return visitor.visit(program);
+}
+
bool Inliner::analyze(Program& program) {
// A threshold of zero indicates that the inliner is completely disabled, so we can just return.
if (fSettings->fInlineThreshold <= 0) {
@@ -1151,7 +1175,7 @@
// idea to inline it.
if (candidate.fIsLargeFunction &&
!(funcDecl->modifiers().fFlags & Modifiers::kInline_Flag) &&
- funcDecl->callCount() > 1) {
+ multiple_calls_to(program, funcDecl)) {
continue;
}