Use SkBitSet for the work list, instead of a set<int>.
This provides an overall ~5% speedup in sksl_medium and sksl_large.
http://screen/9d992SKbYf7DzhW
Change-Id: Ia006a0b6b9f5d3d4e5b2298c64c491a4e04464c0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/322436
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 b4bb2ac..27ff41c 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -33,6 +33,7 @@
#include "src/sksl/ir/SkSLTernaryExpression.h"
#include "src/sksl/ir/SkSLUnresolvedFunction.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"
+#include "src/utils/SkBitSet.h"
#include <fstream>
@@ -550,7 +551,7 @@
}
}
-void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
+void Compiler::scanCFG(CFG* cfg, BlockId blockId, SkBitSet* processedSet) {
BasicBlock& block = cfg->fBlocks[blockId];
// compute definitions after this block
@@ -569,15 +570,15 @@
std::unique_ptr<Expression>* e1 = pair.second;
auto found = exit.fBefore.find(pair.first);
if (found == exit.fBefore.end()) {
- // exit has no definition for it, just copy it
- workList->insert(exitId);
+ // exit has no definition for it, just copy it and reprocess exit block
+ processedSet->reset(exitId);
exit.fBefore[pair.first] = e1;
} else {
// exit has a (possibly different) value already defined
std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
if (e1 != e2) {
- // definition has changed, merge and add exit block to worklist
- workList->insert(exitId);
+ // definition has changed, merge and reprocess the exit block
+ processedSet->reset(exitId);
if (e1 && e2) {
exit.fBefore[pair.first] =
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression;
@@ -655,14 +656,12 @@
void Compiler::computeDataFlow(CFG* cfg) {
cfg->fBlocks[cfg->fStart].fBefore = compute_start_state(*cfg);
- std::set<BlockId> workList;
- for (BlockId i = 0; i < cfg->fBlocks.size(); i++) {
- workList.insert(i);
- }
- while (workList.size()) {
- BlockId next = *workList.begin();
- workList.erase(workList.begin());
- this->scanCFG(cfg, next, &workList);
+
+ // We set bits in the "processed" set after a block has been scanned.
+ SkBitSet processedSet(cfg->fBlocks.size());
+ while (SkBitSet::OptionalIndex blockId = processedSet.findFirstUnset()) {
+ processedSet.set(*blockId);
+ this->scanCFG(cfg, *blockId, &processedSet);
}
}