aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl/SkSLCFGGenerator.cpp
diff options
context:
space:
mode:
authorGravatar Ethan Nicholas <ethannicholas@google.com>2017-02-02 16:11:39 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-02-03 14:37:55 +0000
commit113628d76176a1ab3e6719c59efff23cd10ab213 (patch)
tree89c7815c9b7e86a4b9b573ee8ecc6bb7a946de2d /src/sksl/SkSLCFGGenerator.cpp
parent3f36369a94d2c49c91bcd0249bf351da36a6d40d (diff)
Added dead variable / code elimination to skslc.
BUG=skia: Change-Id: Ib037730803a8f222f099de0e001fe06ad452a22c Reviewed-on: https://skia-review.googlesource.com/7584 Commit-Queue: Ethan Nicholas <ethannicholas@google.com> Reviewed-by: Ben Wagner <benjaminwagner@google.com>
Diffstat (limited to 'src/sksl/SkSLCFGGenerator.cpp')
-rw-r--r--src/sksl/SkSLCFGGenerator.cpp273
1 files changed, 239 insertions, 34 deletions
diff --git a/src/sksl/SkSLCFGGenerator.cpp b/src/sksl/SkSLCFGGenerator.cpp
index 31bace9fb7..f3e4f92396 100644
--- a/src/sksl/SkSLCFGGenerator.cpp
+++ b/src/sksl/SkSLCFGGenerator.cpp
@@ -55,7 +55,7 @@ void CFG::dump() {
const char* separator = "";
for (auto iter = fBlocks[i].fBefore.begin(); iter != fBlocks[i].fBefore.end(); iter++) {
printf("%s%s = %s", separator, iter->first->description().c_str(),
- *iter->second ? (*iter->second)->description().c_str() : "<undefined>");
+ iter->second ? (*iter->second)->description().c_str() : "<undefined>");
separator = ", ";
}
printf("\nEntrances: ");
@@ -67,9 +67,9 @@ void CFG::dump() {
printf("\n");
for (size_t j = 0; j < fBlocks[i].fNodes.size(); j++) {
BasicBlock::Node& n = fBlocks[i].fNodes[j];
- printf("Node %d: %s\n", (int) j, n.fKind == BasicBlock::Node::kExpression_Kind
+ printf("Node %d (%p): %s\n", (int) j, &n, n.fKind == BasicBlock::Node::kExpression_Kind
? (*n.fExpression)->description().c_str()
- : n.fStatement->description().c_str());
+ : (*n.fStatement)->description().c_str());
}
printf("Exits: ");
separator = "";
@@ -81,6 +81,203 @@ void CFG::dump() {
}
}
+bool BasicBlock::tryRemoveExpressionBefore(std::vector<BasicBlock::Node>::iterator* iter,
+ Expression* e) {
+ if (e->fKind == Expression::kTernary_Kind) {
+ return false;
+ }
+ bool result;
+ if ((*iter)->fKind == BasicBlock::Node::kExpression_Kind) {
+ ASSERT((*iter)->fExpression->get() != e);
+ Expression* old = (*iter)->fExpression->get();
+ do {
+ if ((*iter) == fNodes.begin()) {
+ SkASSERT(false);
+ return false;
+ }
+ --(*iter);
+ } while ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
+ (*iter)->fExpression->get() != e);
+ result = this->tryRemoveExpression(iter);
+ while ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
+ (*iter)->fExpression->get() != old) {
+ ASSERT(*iter != fNodes.end());
+ ++(*iter);
+ }
+ } else {
+ Statement* old = (*iter)->fStatement->get();
+ do {
+ if ((*iter) == fNodes.begin()) {
+ SkASSERT(false);
+ return false;
+ }
+ --(*iter);
+ } while ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
+ (*iter)->fExpression->get() != e);
+ result = this->tryRemoveExpression(iter);
+ while ((*iter)->fKind != BasicBlock::Node::kStatement_Kind ||
+ (*iter)->fStatement->get() != old) {
+ ASSERT(*iter != fNodes.end());
+ ++(*iter);
+ }
+ }
+ return result;
+}
+
+bool BasicBlock::tryRemoveLValueBefore(std::vector<BasicBlock::Node>::iterator* iter,
+ Expression* lvalue) {
+ switch (lvalue->fKind) {
+ case Expression::kVariableReference_Kind:
+ return true;
+ case Expression::kSwizzle_Kind:
+ return this->tryRemoveLValueBefore(iter, ((Swizzle*) lvalue)->fBase.get());
+ case Expression::kFieldAccess_Kind:
+ return this->tryRemoveLValueBefore(iter, ((FieldAccess*) lvalue)->fBase.get());
+ case Expression::kIndex_Kind:
+ if (!this->tryRemoveLValueBefore(iter, ((IndexExpression*) lvalue)->fBase.get())) {
+ return false;
+ }
+ return this->tryRemoveExpressionBefore(iter, ((IndexExpression*) lvalue)->fIndex.get());
+ default:
+ SkDebugf("invalid lvalue: %s\n", lvalue->description().c_str());
+ ASSERT(false);
+ return false;
+ }
+}
+
+bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* iter) {
+ ASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind);
+ Expression* expr = (*iter)->fExpression->get();
+ switch (expr->fKind) {
+ case Expression::kBinary_Kind: {
+ BinaryExpression* b = (BinaryExpression*) expr;
+ if (b->fOperator == Token::EQ) {
+ if (!this->tryRemoveLValueBefore(iter, b->fLeft.get())) {
+ return false;
+ }
+ } else if (!this->tryRemoveExpressionBefore(iter, b->fLeft.get())) {
+ return false;
+ }
+ if (!this->tryRemoveExpressionBefore(iter, b->fRight.get())) {
+ return false;
+ }
+ ASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind &&
+ (*iter)->fExpression->get() == expr);
+ *iter = fNodes.erase(*iter);
+ return true;
+ }
+ case Expression::kTernary_Kind: {
+ // ternaries cross basic block boundaries, must regenerate the CFG to remove it
+ return false;
+ }
+ case Expression::kFieldAccess_Kind: {
+ FieldAccess* f = (FieldAccess*) expr;
+ if (!this->tryRemoveExpressionBefore(iter, f->fBase.get())) {
+ return false;
+ }
+ *iter = fNodes.erase(*iter);
+ return true;
+ }
+ case Expression::kSwizzle_Kind: {
+ Swizzle* s = (Swizzle*) expr;
+ if (!this->tryRemoveExpressionBefore(iter, s->fBase.get())) {
+ return false;
+ }
+ *iter = fNodes.erase(*iter);
+ return true;
+ }
+ case Expression::kIndex_Kind: {
+ IndexExpression* idx = (IndexExpression*) expr;
+ if (!this->tryRemoveExpressionBefore(iter, idx->fBase.get())) {
+ return false;
+ }
+ if (!this->tryRemoveExpressionBefore(iter, idx->fIndex.get())) {
+ return false;
+ }
+ *iter = fNodes.erase(*iter);
+ return true;
+ }
+ case Expression::kConstructor_Kind: {
+ Constructor* c = (Constructor*) expr;
+ for (auto& arg : c->fArguments) {
+ if (!this->tryRemoveExpressionBefore(iter, arg.get())) {
+ return false;
+ }
+ ASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind &&
+ (*iter)->fExpression->get() == expr);
+ }
+ *iter = fNodes.erase(*iter);
+ return true;
+ }
+ case Expression::kFunctionCall_Kind: {
+ FunctionCall* f = (FunctionCall*) expr;
+ for (auto& arg : f->fArguments) {
+ if (!this->tryRemoveExpressionBefore(iter, arg.get())) {
+ return false;
+ }
+ ASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind &&
+ (*iter)->fExpression->get() == expr);
+ }
+ *iter = fNodes.erase(*iter);
+ return true;
+ }
+ case Expression::kPrefix_Kind:
+ if (!this->tryRemoveExpressionBefore(iter,
+ ((PrefixExpression*) expr)->fOperand.get())) {
+ return false;
+ }
+ *iter = fNodes.erase(*iter);
+ return true;
+ case Expression::kPostfix_Kind:
+ if (!this->tryRemoveExpressionBefore(iter,
+ ((PrefixExpression*) expr)->fOperand.get())) {
+ return false;
+ }
+ *iter = fNodes.erase(*iter);
+ return true;
+ case Expression::kBoolLiteral_Kind: // fall through
+ case Expression::kFloatLiteral_Kind: // fall through
+ case Expression::kIntLiteral_Kind: // fall through
+ case Expression::kVariableReference_Kind:
+ *iter = fNodes.erase(*iter);
+ return true;
+ default:
+ SkDebugf("unhandled expression: %s\n", expr->description().c_str());
+ ASSERT(false);
+ return false;
+ }
+}
+
+bool BasicBlock::tryInsertExpression(std::vector<BasicBlock::Node>::iterator* iter,
+ std::unique_ptr<Expression>* expr) {
+ switch ((*expr)->fKind) {
+ case Expression::kBinary_Kind: {
+ BinaryExpression* b = (BinaryExpression*) expr->get();
+ if (!this->tryInsertExpression(iter, &b->fRight)) {
+ return false;
+ }
+ ++(*iter);
+ if (!this->tryInsertExpression(iter, &b->fLeft)) {
+ return false;
+ }
+ ++(*iter);
+ BasicBlock::Node node = { BasicBlock::Node::kExpression_Kind, true, expr, nullptr };
+ *iter = fNodes.insert(*iter, node);
+ return true;
+ }
+ case Expression::kBoolLiteral_Kind: // fall through
+ case Expression::kFloatLiteral_Kind: // fall through
+ case Expression::kIntLiteral_Kind: // fall through
+ case Expression::kVariableReference_Kind: {
+ BasicBlock::Node node = { BasicBlock::Node::kExpression_Kind, true, expr, nullptr };
+ *iter = fNodes.insert(*iter, node);
+ return true;
+ }
+ default:
+ return false;
+ }
+}
+
void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool constantPropagate) {
ASSERT(e);
switch ((*e)->fKind) {
@@ -177,6 +374,8 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
case Expression::kTernary_Kind: {
TernaryExpression* t = (TernaryExpression*) e->get();
this->addExpression(cfg, &t->fTest, constantPropagate);
+ cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
+ constantPropagate, e, nullptr });
BlockId start = cfg.fCurrent;
cfg.newBlock();
this->addExpression(cfg, &t->fIfTrue, constantPropagate);
@@ -218,24 +417,26 @@ void CFGGenerator::addLValue(CFG& cfg, std::unique_ptr<Expression>* e) {
}
}
-void CFGGenerator::addStatement(CFG& cfg, const Statement* s) {
- switch (s->fKind) {
+void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
+ switch ((*s)->fKind) {
case Statement::kBlock_Kind:
- for (const auto& child : ((const Block*) s)->fStatements) {
- addStatement(cfg, child.get());
+ for (auto& child : ((Block&) **s).fStatements) {
+ addStatement(cfg, &child);
}
break;
case Statement::kIf_Kind: {
- IfStatement* ifs = (IfStatement*) s;
- this->addExpression(cfg, &ifs->fTest, true);
+ IfStatement& ifs = (IfStatement&) **s;
+ this->addExpression(cfg, &ifs.fTest, true);
+ cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
+ nullptr, s });
BlockId start = cfg.fCurrent;
cfg.newBlock();
- this->addStatement(cfg, ifs->fIfTrue.get());
+ this->addStatement(cfg, &ifs.fIfTrue);
BlockId next = cfg.newBlock();
- if (ifs->fIfFalse) {
+ if (ifs.fIfFalse) {
cfg.fCurrent = start;
cfg.newBlock();
- this->addStatement(cfg, ifs->fIfFalse.get());
+ this->addStatement(cfg, &ifs.fIfFalse);
cfg.addExit(cfg.fCurrent, next);
cfg.fCurrent = next;
} else {
@@ -244,14 +445,16 @@ void CFGGenerator::addStatement(CFG& cfg, const Statement* s) {
break;
}
case Statement::kExpression_Kind: {
- this->addExpression(cfg, &((ExpressionStatement&) *s).fExpression, true);
+ this->addExpression(cfg, &((ExpressionStatement&) **s).fExpression, true);
+ cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
+ nullptr, s });
break;
}
case Statement::kVarDeclarations_Kind: {
- VarDeclarationsStatement& decls = ((VarDeclarationsStatement&) *s);
+ VarDeclarationsStatement& decls = ((VarDeclarationsStatement&) **s);
for (auto& vd : decls.fDeclaration->fVars) {
- if (vd.fValue) {
- this->addExpression(cfg, &vd.fValue, true);
+ if (vd->fValue) {
+ this->addExpression(cfg, &vd->fValue, true);
}
}
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
@@ -264,7 +467,7 @@ void CFGGenerator::addStatement(CFG& cfg, const Statement* s) {
cfg.fCurrent = cfg.newIsolatedBlock();
break;
case Statement::kReturn_Kind: {
- ReturnStatement& r = ((ReturnStatement&) *s);
+ ReturnStatement& r = ((ReturnStatement&) **s);
if (r.fExpression) {
this->addExpression(cfg, &r.fExpression, true);
}
@@ -286,16 +489,16 @@ void CFGGenerator::addStatement(CFG& cfg, const Statement* s) {
cfg.fCurrent = cfg.newIsolatedBlock();
break;
case Statement::kWhile_Kind: {
- WhileStatement* w = (WhileStatement*) s;
+ WhileStatement& w = (WhileStatement&) **s;
BlockId loopStart = cfg.newBlock();
fLoopContinues.push(loopStart);
BlockId loopExit = cfg.newIsolatedBlock();
fLoopExits.push(loopExit);
- this->addExpression(cfg, &w->fTest, true);
+ this->addExpression(cfg, &w.fTest, true);
BlockId test = cfg.fCurrent;
cfg.addExit(test, loopExit);
cfg.newBlock();
- this->addStatement(cfg, w->fStatement.get());
+ this->addStatement(cfg, &w.fStatement);
cfg.addExit(cfg.fCurrent, loopStart);
fLoopContinues.pop();
fLoopExits.pop();
@@ -303,13 +506,13 @@ void CFGGenerator::addStatement(CFG& cfg, const Statement* s) {
break;
}
case Statement::kDo_Kind: {
- DoStatement* d = (DoStatement*) s;
+ DoStatement& d = (DoStatement&) **s;
BlockId loopStart = cfg.newBlock();
fLoopContinues.push(loopStart);
BlockId loopExit = cfg.newIsolatedBlock();
fLoopExits.push(loopExit);
- this->addStatement(cfg, d->fStatement.get());
- this->addExpression(cfg, &d->fTest, true);
+ this->addStatement(cfg, &d.fStatement);
+ this->addExpression(cfg, &d.fTest, true);
cfg.addExit(cfg.fCurrent, loopExit);
cfg.addExit(cfg.fCurrent, loopStart);
fLoopContinues.pop();
@@ -318,26 +521,26 @@ void CFGGenerator::addStatement(CFG& cfg, const Statement* s) {
break;
}
case Statement::kFor_Kind: {
- ForStatement* f = (ForStatement*) s;
- if (f->fInitializer) {
- this->addStatement(cfg, f->fInitializer.get());
+ ForStatement& f = (ForStatement&) **s;
+ if (f.fInitializer) {
+ this->addStatement(cfg, &f.fInitializer);
}
BlockId loopStart = cfg.newBlock();
BlockId next = cfg.newIsolatedBlock();
fLoopContinues.push(next);
BlockId loopExit = cfg.newIsolatedBlock();
fLoopExits.push(loopExit);
- if (f->fTest) {
- this->addExpression(cfg, &f->fTest, true);
+ if (f.fTest) {
+ this->addExpression(cfg, &f.fTest, true);
BlockId test = cfg.fCurrent;
cfg.addExit(test, loopExit);
}
cfg.newBlock();
- this->addStatement(cfg, f->fStatement.get());
+ this->addStatement(cfg, &f.fStatement);
cfg.addExit(cfg.fCurrent, next);
cfg.fCurrent = next;
- if (f->fNext) {
- this->addExpression(cfg, &f->fNext, true);
+ if (f.fNext) {
+ this->addExpression(cfg, &f.fNext, true);
}
cfg.addExit(cfg.fCurrent, loopStart);
fLoopContinues.pop();
@@ -345,17 +548,19 @@ void CFGGenerator::addStatement(CFG& cfg, const Statement* s) {
cfg.fCurrent = loopExit;
break;
}
+ case Statement::kNop_Kind:
+ break;
default:
- printf("statement: %s\n", s->description().c_str());
+ printf("statement: %s\n", (*s)->description().c_str());
ABORT("unsupported statement kind");
}
}
-CFG CFGGenerator::getCFG(const FunctionDefinition& f) {
+CFG CFGGenerator::getCFG(FunctionDefinition& f) {
CFG result;
result.fStart = result.newBlock();
result.fCurrent = result.fStart;
- this->addStatement(result, f.fBody.get());
+ this->addStatement(result, &f.fBody);
result.newBlock();
result.fExit = result.fCurrent;
return result;