aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl/SkSLCompiler.cpp
diff options
context:
space:
mode:
authorGravatar Ethan Nicholas <ethannicholas@google.com>2017-01-19 16:31:32 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-19 16:31:44 +0000
commit6415e0d2417d133af28ac523400d3f958d2bcd1c (patch)
tree92fbe77322ba50e984f6d85870f40bad70ccacf4 /src/sksl/SkSLCompiler.cpp
parentf54b07121f81a56145fb118a2e18841fc135717d (diff)
Revert "Added constant propagation and better variable liveness tracking to"
This reverts commit f54b07121f81a56145fb118a2e18841fc135717d. Reason for revert: ASAN failure Original change's description: > Added constant propagation and better variable liveness tracking to > skslc. > > This allows skslc to track the values of variables with constant > values across multiple statements and replace variable references with > constant values where appropriate. > > The improved liveness tracking allows skslc to realize that a > variable is no longer alive if all references to it have been > replaced. It is not yet doing much with this information; better > dead code elimination is coming in a followup change. > > BUG=skia: > > Change-Id: I6bf267d478b769caf0063ac3597dc16bbe618cb4 > Reviewed-on: https://skia-review.googlesource.com/7033 > Commit-Queue: Ethan Nicholas <ethannicholas@google.com> > Reviewed-by: Greg Daniel <egdaniel@google.com> > TBR=egdaniel@google.com,ethannicholas@google.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia: Change-Id: Id2e26bce96b27df73948f8b32d3dff2e358ae0d6 Reviewed-on: https://skia-review.googlesource.com/7274 Commit-Queue: Ethan Nicholas <ethannicholas@google.com> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Diffstat (limited to 'src/sksl/SkSLCompiler.cpp')
-rw-r--r--src/sksl/SkSLCompiler.cpp119
1 files changed, 33 insertions, 86 deletions
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 743745ad14..9faf836156 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -156,8 +156,8 @@ Compiler::~Compiler() {
}
// add the definition created by assigning to the lvalue to the definition set
-void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
- DefinitionMap* definitions) {
+void Compiler::addDefinition(const Expression* lvalue, const Expression* expr,
+ std::unordered_map<const Variable*, const Expression*>* definitions) {
switch (lvalue->fKind) {
case Expression::kVariableReference_Kind: {
const Variable& var = ((VariableReference*) lvalue)->fVariable;
@@ -174,19 +174,19 @@ void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expressio
// but since we pass foo as a whole it is flagged as an error) unless we perform a much
// more complicated whole-program analysis. This is probably good enough.
this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
- (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
+ fContext.fDefined_Expression.get(),
definitions);
break;
case Expression::kIndex_Kind:
// see comments in Swizzle
this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
- (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
+ fContext.fDefined_Expression.get(),
definitions);
break;
case Expression::kFieldAccess_Kind:
// see comments in Swizzle
this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
- (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
+ fContext.fDefined_Expression.get(),
definitions);
break;
default:
@@ -197,58 +197,25 @@ void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expressio
// add local variables defined by this node to the set
void Compiler::addDefinitions(const BasicBlock::Node& node,
- DefinitionMap* definitions) {
+ std::unordered_map<const Variable*, const Expression*>* definitions) {
switch (node.fKind) {
case BasicBlock::Node::kExpression_Kind: {
- ASSERT(node.fExpression);
- const Expression* expr = (Expression*) node.fExpression->get();
- switch (expr->fKind) {
- case Expression::kBinary_Kind: {
- BinaryExpression* b = (BinaryExpression*) expr;
- if (b->fOperator == Token::EQ) {
- this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
- } else if (Token::IsAssignment(b->fOperator)) {
- this->addDefinition(
- b->fLeft.get(),
- (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
- definitions);
-
- }
- break;
- }
- case Expression::kPrefix_Kind: {
- const PrefixExpression* p = (PrefixExpression*) expr;
- if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
- this->addDefinition(
- p->fOperand.get(),
- (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
- definitions);
- }
- break;
+ const Expression* expr = (Expression*) node.fNode;
+ if (expr->fKind == Expression::kBinary_Kind) {
+ const BinaryExpression* b = (BinaryExpression*) expr;
+ if (b->fOperator == Token::EQ) {
+ this->addDefinition(b->fLeft.get(), b->fRight.get(), definitions);
}
- case Expression::kPostfix_Kind: {
- const PostfixExpression* p = (PostfixExpression*) expr;
- if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
- this->addDefinition(
- p->fOperand.get(),
- (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
- definitions);
-
- }
- break;
- }
- default:
- break;
}
break;
}
case BasicBlock::Node::kStatement_Kind: {
- const Statement* stmt = (Statement*) node.fStatement;
+ const Statement* stmt = (Statement*) node.fNode;
if (stmt->fKind == Statement::kVarDeclarations_Kind) {
- VarDeclarationsStatement* vd = (VarDeclarationsStatement*) stmt;
- for (VarDeclaration& decl : vd->fDeclaration->fVars) {
+ const VarDeclarationsStatement* vd = (VarDeclarationsStatement*) stmt;
+ for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
if (decl.fValue) {
- (*definitions)[decl.fVar] = &decl.fValue;
+ (*definitions)[decl.fVar] = decl.fValue.get();
}
}
}
@@ -261,7 +228,7 @@ void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
BasicBlock& block = cfg->fBlocks[blockId];
// compute definitions after this block
- DefinitionMap after = block.fBefore;
+ std::unordered_map<const Variable*, const Expression*> after = block.fBefore;
for (const BasicBlock::Node& n : block.fNodes) {
this->addDefinitions(n, &after);
}
@@ -270,20 +237,19 @@ void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
for (BlockId exitId : block.fExits) {
BasicBlock& exit = cfg->fBlocks[exitId];
for (const auto& pair : after) {
- 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);
+ const Expression* e1 = pair.second;
+ if (exit.fBefore.find(pair.first) == exit.fBefore.end()) {
exit.fBefore[pair.first] = e1;
} else {
- // exit has a (possibly different) value already defined
- std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
+ const Expression* e2 = exit.fBefore[pair.first];
if (e1 != e2) {
// definition has changed, merge and add exit block to worklist
workList->insert(exitId);
- exit.fBefore[pair.first] =
- (std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
+ if (!e1 || !e2) {
+ exit.fBefore[pair.first] = nullptr;
+ } else {
+ exit.fBefore[pair.first] = fContext.fDefined_Expression.get();
+ }
}
}
}
@@ -292,13 +258,12 @@ void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
// returns a map which maps all local variables in the function to null, indicating that their value
// is initially unknown
-static DefinitionMap compute_start_state(const CFG& cfg) {
- DefinitionMap result;
+static std::unordered_map<const Variable*, const Expression*> compute_start_state(const CFG& cfg) {
+ std::unordered_map<const Variable*, const Expression*> result;
for (const auto& block : cfg.fBlocks) {
for (const auto& node : block.fNodes) {
if (node.fKind == BasicBlock::Node::kStatement_Kind) {
- ASSERT(node.fStatement);
- const Statement* s = node.fStatement;
+ const Statement* s = (Statement*) node.fNode;
if (s->fKind == Statement::kVarDeclarations_Kind) {
const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
@@ -330,37 +295,19 @@ void Compiler::scanCFG(const FunctionDefinition& f) {
for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
cfg.fBlocks[i].fNodes.size()) {
- Position p;
- switch (cfg.fBlocks[i].fNodes[0].fKind) {
- case BasicBlock::Node::kStatement_Kind:
- p = cfg.fBlocks[i].fNodes[0].fStatement->fPosition;
- break;
- case BasicBlock::Node::kExpression_Kind:
- p = (*cfg.fBlocks[i].fNodes[0].fExpression)->fPosition;
- break;
- }
- this->error(p, SkString("unreachable"));
+ this->error(cfg.fBlocks[i].fNodes[0].fNode->fPosition, SkString("unreachable"));
}
}
if (fErrorCount) {
return;
}
- // check for undefined variables, perform constant propagation
- for (BasicBlock& b : cfg.fBlocks) {
- DefinitionMap definitions = b.fBefore;
- for (BasicBlock::Node& n : b.fNodes) {
+ // check for undefined variables
+ for (const BasicBlock& b : cfg.fBlocks) {
+ std::unordered_map<const Variable*, const Expression*> definitions = b.fBefore;
+ for (const BasicBlock::Node& n : b.fNodes) {
if (n.fKind == BasicBlock::Node::kExpression_Kind) {
- ASSERT(n.fExpression);
- Expression* expr = n.fExpression->get();
- if (n.fConstantPropagation) {
- std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator,
- definitions);
- if (optimized) {
- n.fExpression->reset(optimized.release());
- expr = n.fExpression->get();
- }
- }
+ const Expression* expr = (const Expression*) n.fNode;
if (expr->fKind == Expression::kVariableReference_Kind) {
const Variable& var = ((VariableReference*) expr)->fVariable;
if (var.fStorage == Variable::kLocal_Storage &&