summaryrefslogtreecommitdiff
path: root/chromium/third_party/skia/src/sksl/SkSLConstantFolder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/src/sksl/SkSLConstantFolder.cpp')
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLConstantFolder.cpp159
1 files changed, 131 insertions, 28 deletions
diff --git a/chromium/third_party/skia/src/sksl/SkSLConstantFolder.cpp b/chromium/third_party/skia/src/sksl/SkSLConstantFolder.cpp
index 39b798113e2..9c11c749384 100644
--- a/chromium/third_party/skia/src/sksl/SkSLConstantFolder.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLConstantFolder.cpp
@@ -15,6 +15,7 @@
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/ir/SkSLConstructorCompound.h"
+#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLConstructorSplat.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLLiteral.h"
@@ -23,7 +24,9 @@
#include "src/sksl/ir/SkSLVariable.h"
#include "src/sksl/ir/SkSLVariableReference.h"
+#include <cfloat>
#include <cmath>
+#include <cstdint>
#include <limits>
#include <optional>
#include <string>
@@ -274,8 +277,36 @@ static std::unique_ptr<Expression> cast_expression(const Context& context,
const Expression& expr,
const Type& type) {
SkASSERT(type.componentType().matches(expr.type().componentType()));
- return expr.type().isScalar() ? ConstructorSplat::Make(context, pos, type, expr.clone())
- : expr.clone(pos);
+ if (expr.type().isScalar()) {
+ if (type.isMatrix()) {
+ return ConstructorDiagonalMatrix::Make(context, pos, type, expr.clone());
+ }
+ if (type.isVector()) {
+ return ConstructorSplat::Make(context, pos, type, expr.clone());
+ }
+ }
+ if (type.matches(expr.type())) {
+ return expr.clone(pos);
+ }
+ // We can't cast matrices into vectors or vice-versa.
+ return nullptr;
+}
+
+static std::unique_ptr<Expression> zero_expression(const Context& context,
+ Position pos,
+ const Type& type) {
+ std::unique_ptr<Expression> zero = Literal::Make(pos, 0.0, &type.componentType());
+ if (type.isScalar()) {
+ return zero;
+ }
+ if (type.isVector()) {
+ return ConstructorSplat::Make(context, pos, type, std::move(zero));
+ }
+ if (type.isMatrix()) {
+ return ConstructorDiagonalMatrix::Make(context, pos, type, std::move(zero));
+ }
+ SkDEBUGFAILF("unsupported type %s", type.description().c_str());
+ return nullptr;
}
static std::unique_ptr<Expression> negate_expression(const Context& context,
@@ -316,7 +347,8 @@ static bool contains_constant_zero(const Expression& expr) {
return false;
}
-static bool is_constant_value(const Expression& expr, double value) {
+// Returns true if the expression contains `value` in every slot.
+static bool is_constant_splat(const Expression& expr, double value) {
int numSlots = expr.type().slotCount();
for (int index = 0; index < numSlots; ++index) {
std::optional<double> slotVal = expr.getConstantValue(index);
@@ -327,6 +359,33 @@ static bool is_constant_value(const Expression& expr, double value) {
return true;
}
+// Returns true if the expression is a square diagonal matrix containing `value`.
+static bool is_constant_diagonal(const Expression& expr, double value) {
+ SkASSERT(expr.type().isMatrix());
+ int columns = expr.type().columns();
+ int rows = expr.type().rows();
+ if (columns != rows) {
+ return false;
+ }
+ int slotIdx = 0;
+ for (int c = 0; c < columns; ++c) {
+ for (int r = 0; r < rows; ++r) {
+ double expectation = (c == r) ? value : 0;
+ std::optional<double> slotVal = expr.getConstantValue(slotIdx++);
+ if (!slotVal.has_value() || *slotVal != expectation) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// Returns true if the expression is a scalar, vector, or diagonal matrix containing `value`.
+static bool is_constant_value(const Expression& expr, double value) {
+ return expr.type().isMatrix() ? is_constant_diagonal(expr, value)
+ : is_constant_splat(expr, value);
+}
+
static bool error_on_divide_by_zero(const Context& context, Position pos, Operator op,
const Expression& right) {
switch (op.kind()) {
@@ -379,6 +438,14 @@ std::unique_ptr<Expression> ConstantFolder::MakeConstantValueForVariable(Positio
return expr;
}
+static bool is_scalar_op_matrix(const Expression& left, const Expression& right) {
+ return left.type().isScalar() && right.type().isMatrix();
+}
+
+static bool is_matrix_op_scalar(const Expression& left, const Expression& right) {
+ return is_scalar_op_matrix(right, left);
+}
+
static std::unique_ptr<Expression> simplify_no_op_arithmetic(const Context& context,
Position pos,
const Expression& left,
@@ -387,55 +454,82 @@ static std::unique_ptr<Expression> simplify_no_op_arithmetic(const Context& cont
const Type& resultType) {
switch (op.kind()) {
case Operator::Kind::PLUS:
- if (is_constant_value(right, 0.0)) { // x + 0
- return cast_expression(context, pos, left, resultType);
+ if (!is_scalar_op_matrix(left, right) && is_constant_splat(right, 0.0)) { // x + 0
+ if (std::unique_ptr<Expression> expr = cast_expression(context, pos, left,
+ resultType)) {
+ return expr;
+ }
}
- if (is_constant_value(left, 0.0)) { // 0 + x
- return cast_expression(context, pos, right, resultType);
+ if (!is_matrix_op_scalar(left, right) && is_constant_splat(left, 0.0)) { // 0 + x
+ if (std::unique_ptr<Expression> expr = cast_expression(context, pos, right,
+ resultType)) {
+ return expr;
+ }
}
break;
case Operator::Kind::STAR:
if (is_constant_value(right, 1.0)) { // x * 1
- return cast_expression(context, pos, left, resultType);
+ if (std::unique_ptr<Expression> expr = cast_expression(context, pos, left,
+ resultType)) {
+ return expr;
+ }
}
if (is_constant_value(left, 1.0)) { // 1 * x
- return cast_expression(context, pos, right, resultType);
+ if (std::unique_ptr<Expression> expr = cast_expression(context, pos, right,
+ resultType)) {
+ return expr;
+ }
}
if (is_constant_value(right, 0.0) && !left.hasSideEffects()) { // x * 0
- return cast_expression(context, pos, right, resultType);
+ return zero_expression(context, pos, resultType);
}
if (is_constant_value(left, 0.0) && !right.hasSideEffects()) { // 0 * x
- return cast_expression(context, pos, left, resultType);
+ return zero_expression(context, pos, resultType);
}
if (is_constant_value(right, -1.0)) { // x * -1 (to `-x`)
- return negate_expression(context, pos, left, resultType);
+ if (std::unique_ptr<Expression> expr = negate_expression(context, pos, left,
+ resultType)) {
+ return expr;
+ }
}
if (is_constant_value(left, -1.0)) { // -1 * x (to `-x`)
- return negate_expression(context, pos, right, resultType);
+ if (std::unique_ptr<Expression> expr = negate_expression(context, pos, right,
+ resultType)) {
+ return expr;
+ }
}
break;
case Operator::Kind::MINUS:
- if (is_constant_value(right, 0.0)) { // x - 0
- return cast_expression(context, pos, left, resultType);
+ if (!is_scalar_op_matrix(left, right) && is_constant_splat(right, 0.0)) { // x - 0
+ if (std::unique_ptr<Expression> expr = cast_expression(context, pos, left,
+ resultType)) {
+ return expr;
+ }
}
- if (is_constant_value(left, 0.0)) { // 0 - x (to `-x`)
- return negate_expression(context, pos, right, resultType);
+ if (!is_matrix_op_scalar(left, right) && is_constant_splat(left, 0.0)) { // 0 - x
+ if (std::unique_ptr<Expression> expr = negate_expression(context, pos, right,
+ resultType)) {
+ return expr;
+ }
}
break;
case Operator::Kind::SLASH:
- if (is_constant_value(right, 1.0)) { // x / 1
- return cast_expression(context, pos, left, resultType);
+ if (!is_scalar_op_matrix(left, right) && is_constant_splat(right, 1.0)) { // x / 1
+ if (std::unique_ptr<Expression> expr = cast_expression(context, pos, left,
+ resultType)) {
+ return expr;
+ }
}
break;
case Operator::Kind::PLUSEQ:
case Operator::Kind::MINUSEQ:
- if (is_constant_value(right, 0.0)) { // x += 0, x -= 0
+ if (is_constant_splat(right, 0.0)) { // x += 0, x -= 0
if (std::unique_ptr<Expression> var = cast_expression(context, pos, left,
- resultType)) {
+ resultType)) {
Analysis::UpdateVariableRefKind(var.get(), VariableRefKind::kRead);
return var;
}
@@ -443,10 +537,19 @@ static std::unique_ptr<Expression> simplify_no_op_arithmetic(const Context& cont
break;
case Operator::Kind::STAREQ:
+ if (is_constant_value(right, 1.0)) { // x *= 1
+ if (std::unique_ptr<Expression> var = cast_expression(context, pos, left,
+ resultType)) {
+ Analysis::UpdateVariableRefKind(var.get(), VariableRefKind::kRead);
+ return var;
+ }
+ }
+ break;
+
case Operator::Kind::SLASHEQ:
- if (is_constant_value(right, 1.0)) { // x *= 1, x /= 1
+ if (is_constant_splat(right, 1.0)) { // x /= 1
if (std::unique_ptr<Expression> var = cast_expression(context, pos, left,
- resultType)) {
+ resultType)) {
Analysis::UpdateVariableRefKind(var.get(), VariableRefKind::kRead);
return var;
}
@@ -464,9 +567,11 @@ template <typename T>
static std::unique_ptr<Expression> fold_float_expression(Position pos,
T result,
const Type* resultType) {
- // If constant-folding this expression would generate a NaN/infinite result, leave it as-is.
if constexpr (!std::is_same<T, bool>::value) {
- if (!std::isfinite(result)) {
+ if (result >= -FLT_MAX && result <= FLT_MAX) {
+ // This result will fit inside a float Literal.
+ } else {
+ // The value is outside the float range or is NaN (all if-checks fail); do not optimize.
return nullptr;
}
}
@@ -557,9 +662,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
// Optimize away no-op arithmetic like `x * 1`, `x *= 1`, `x + 0`, `x * 0`, `0 / x`, etc.
const Type& leftType = left->type();
const Type& rightType = right->type();
- if (context.fConfig->fSettings.fOptimize &&
- (leftType.isScalar() || leftType.isVector()) &&
- (rightType.isScalar() || rightType.isVector())) {
+ if (context.fConfig->fSettings.fOptimize) {
if (std::unique_ptr<Expression> expr = simplify_no_op_arithmetic(context, pos, *left, op,
*right, resultType)) {
return expr;