aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl/SkSLIRGenerator.cpp
diff options
context:
space:
mode:
authorGravatar Ethan Nicholas <ethannicholas@google.com>2017-01-19 13:32:00 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-19 20:11:40 +0000
commit86a43405fb3f83f6d45581959df5f7321487ae7e (patch)
tree4d367433d67af533d96fcbc80abe192010219427 /src/sksl/SkSLIRGenerator.cpp
parent4f364fd951eac36adbc1c8719f3e7c42974dfad1 (diff)
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: I068c5d2e9a362e75299b1de1f4575339f5ddc3bb Reviewed-on: https://skia-review.googlesource.com/7302 Reviewed-by: Ethan Nicholas <ethannicholas@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Diffstat (limited to 'src/sksl/SkSLIRGenerator.cpp')
-rw-r--r--src/sksl/SkSLIRGenerator.cpp78
1 files changed, 26 insertions, 52 deletions
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 9f06c97d11..55d9d2c8d6 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -551,11 +551,11 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte
}
}
Type* type = new Type(intf.fPosition, intf.fInterfaceName, fields);
- fSymbolTable->takeOwnership(type);
+ old->takeOwnership(type);
SkString name = intf.fValueName.size() > 0 ? intf.fValueName : intf.fInterfaceName;
Variable* var = new Variable(intf.fPosition, intf.fModifiers, name, *type,
Variable::kGlobal_Storage);
- fSymbolTable->takeOwnership(var);
+ old->takeOwnership(var);
if (intf.fValueName.size()) {
old->addWithoutOwnership(intf.fValueName, var);
} else {
@@ -624,19 +624,22 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier&
f->fFunctions));
}
case Symbol::kVariable_Kind: {
- const Variable* var = (const Variable*) result;
- this->markReadFrom(*var);
+ Variable* var = (Variable*) result;
if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN &&
fSettings->fFlipY &&
(!fSettings->fCaps || !fSettings->fCaps->fragCoordConventionsExtensionString())) {
fInputs.fRTHeight = true;
}
- return std::unique_ptr<VariableReference>(new VariableReference(identifier.fPosition,
- *var));
+ // default to kRead_RefKind; this will be corrected later if the variable is written to
+ return std::unique_ptr<VariableReference>(new VariableReference(
+ identifier.fPosition,
+ *var,
+ VariableReference::kRead_RefKind));
}
case Symbol::kField_Kind: {
const Field* field = (const Field*) result;
- VariableReference* base = new VariableReference(identifier.fPosition, field->fOwner);
+ VariableReference* base = new VariableReference(identifier.fPosition, field->fOwner,
+ VariableReference::kRead_RefKind);
return std::unique_ptr<Expression>(new FieldAccess(
std::unique_ptr<Expression>(base),
field->fFieldIndex,
@@ -690,28 +693,6 @@ static bool is_matrix_multiply(const Type& left, const Type& right) {
return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
}
-static bool is_assignment(Token::Kind op) {
- switch (op) {
- case Token::EQ: // fall through
- case Token::PLUSEQ: // fall through
- case Token::MINUSEQ: // fall through
- case Token::STAREQ: // fall through
- case Token::SLASHEQ: // fall through
- case Token::PERCENTEQ: // fall through
- case Token::SHLEQ: // fall through
- case Token::SHREQ: // fall through
- case Token::BITWISEOREQ: // fall through
- case Token::BITWISEXOREQ: // fall through
- case Token::BITWISEANDEQ: // fall through
- case Token::LOGICALOREQ: // fall through
- case Token::LOGICALXOREQ: // fall through
- case Token::LOGICALANDEQ:
- return true;
- default:
- return false;
- }
-}
-
/**
* Determines the operand and result types of a binary expression. Returns true if the expression is
* legal, false otherwise. If false, the values of the out parameters are undefined.
@@ -842,14 +823,9 @@ static bool determine_binary_type(const Context& context,
return false;
}
-/**
- * If both operands are compile-time constants and can be folded, returns an expression representing
- * the folded value. Otherwise, returns null. Note that unlike most other functions here, null does
- * not represent a compilation error.
- */
std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
Token::Kind op,
- const Expression& right) {
+ const Expression& right) const {
// Note that we expressly do not worry about precision and overflow here -- we use the maximum
// precision to calculate the results and hope the result makes sense. The plan is to move the
// Skia caps into SkSL, so we have access to all of them including the precisions of the various
@@ -943,15 +919,16 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
const Type* rightType;
const Type* resultType;
if (!determine_binary_type(fContext, expression.fOperator, left->fType, right->fType, &leftType,
- &rightType, &resultType, !is_assignment(expression.fOperator))) {
+ &rightType, &resultType,
+ !Token::IsAssignment(expression.fOperator))) {
fErrors.error(expression.fPosition, "type mismatch: '" +
Token::OperatorName(expression.fOperator) +
"' cannot operate on '" + left->fType.fName +
"', '" + right->fType.fName + "'");
return nullptr;
}
- if (is_assignment(expression.fOperator)) {
- this->markWrittenTo(*left);
+ if (Token::IsAssignment(expression.fOperator)) {
+ this->markWrittenTo(*left, expression.fOperator != Token::EQ);
}
left = this->coerce(std::move(left), *leftType);
right = this->coerce(std::move(right), *rightType);
@@ -1051,7 +1028,7 @@ std::unique_ptr<Expression> IRGenerator::call(Position position,
return nullptr;
}
if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
- this->markWrittenTo(*arguments[i]);
+ this->markWrittenTo(*arguments[i], true);
}
}
return std::unique_ptr<FunctionCall>(new FunctionCall(position, *returnType, function,
@@ -1261,7 +1238,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
"' cannot operate on '" + base->fType.description() + "'");
return nullptr;
}
- this->markWrittenTo(*base);
+ this->markWrittenTo(*base, true);
break;
case Token::MINUSMINUS:
if (!base->fType.isNumber()) {
@@ -1270,7 +1247,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
"' cannot operate on '" + base->fType.description() + "'");
return nullptr;
}
- this->markWrittenTo(*base);
+ this->markWrittenTo(*base, true);
break;
case Token::LOGICALNOT:
if (base->fType != *fContext.fBool_Type) {
@@ -1464,7 +1441,7 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
"'++' cannot operate on '" + base->fType.description() + "'");
return nullptr;
}
- this->markWrittenTo(*base);
+ this->markWrittenTo(*base, true);
return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
Token::PLUSPLUS));
case ASTSuffix::kPostDecrement_Kind:
@@ -1473,7 +1450,7 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
"'--' cannot operate on '" + base->fType.description() + "'");
return nullptr;
}
- this->markWrittenTo(*base);
+ this->markWrittenTo(*base, true);
return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
Token::MINUSMINUS));
default:
@@ -1496,10 +1473,6 @@ void IRGenerator::checkValid(const Expression& expr) {
}
}
-void IRGenerator::markReadFrom(const Variable& var) {
- var.fIsReadFrom = true;
-}
-
static bool has_duplicates(const Swizzle& swizzle) {
int bits = 0;
for (int idx : swizzle.fComponents) {
@@ -1513,7 +1486,7 @@ static bool has_duplicates(const Swizzle& swizzle) {
return false;
}
-void IRGenerator::markWrittenTo(const Expression& expr) {
+void IRGenerator::markWrittenTo(const Expression& expr, bool readWrite) {
switch (expr.fKind) {
case Expression::kVariableReference_Kind: {
const Variable& var = ((VariableReference&) expr).fVariable;
@@ -1521,21 +1494,22 @@ void IRGenerator::markWrittenTo(const Expression& expr) {
fErrors.error(expr.fPosition,
"cannot modify immutable variable '" + var.fName + "'");
}
- var.fIsWrittenTo = true;
+ ((VariableReference&) expr).setRefKind(readWrite ? VariableReference::kReadWrite_RefKind
+ : VariableReference::kWrite_RefKind);
break;
}
case Expression::kFieldAccess_Kind:
- this->markWrittenTo(*((FieldAccess&) expr).fBase);
+ this->markWrittenTo(*((FieldAccess&) expr).fBase, readWrite);
break;
case Expression::kSwizzle_Kind:
if (has_duplicates((Swizzle&) expr)) {
fErrors.error(expr.fPosition,
"cannot write to the same swizzle field more than once");
}
- this->markWrittenTo(*((Swizzle&) expr).fBase);
+ this->markWrittenTo(*((Swizzle&) expr).fBase, readWrite);
break;
case Expression::kIndex_Kind:
- this->markWrittenTo(*((IndexExpression&) expr).fBase);
+ this->markWrittenTo(*((IndexExpression&) expr).fBase, readWrite);
break;
default:
fErrors.error(expr.fPosition, "cannot assign to '" + expr.description() + "'");