Allow prefix-expressions in IsSameExpressionTree.
This will allow expressions like `-x == -x` or `!y == !y` to be detected as matching expressions (which enables various constant-folding paths). (Also, migrated the analysis code into a separate cpp.) Change-Id: I3e317fdaed3762f8fa19e684a5ed557fc9348c7c Reviewed-on: https://skia-review.googlesource.com/c/skia/+/527617 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: John Stiles <johnstiles@google.com> Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
759deb9ec2
commit
d0242346b8
@ -87,6 +87,7 @@ skia_sksl_sources = [
|
||||
"$_src/sksl/analysis/SkSLFinalizationChecks.cpp",
|
||||
"$_src/sksl/analysis/SkSLGetLoopUnrollInfo.cpp",
|
||||
"$_src/sksl/analysis/SkSLIsConstantExpression.cpp",
|
||||
"$_src/sksl/analysis/SkSLIsSameExpressionTree.cpp",
|
||||
"$_src/sksl/analysis/SkSLNoOpErrorReporter.h",
|
||||
"$_src/sksl/analysis/SkSLProgramUsage.cpp",
|
||||
"$_src/sksl/analysis/SkSLProgramVisitor.h",
|
||||
|
@ -45,6 +45,7 @@ cc_library(
|
||||
"//src/sksl/analysis:SkSLFinalizationChecks_src",
|
||||
"//src/sksl/analysis:SkSLGetLoopUnrollInfo_src",
|
||||
"//src/sksl/analysis:SkSLIsConstantExpression_src",
|
||||
"//src/sksl/analysis:SkSLIsSameExpressionTree_src",
|
||||
"//src/sksl/analysis:SkSLProgramUsage_src",
|
||||
"//src/sksl/analysis:SkSLSwitchCaseContainsExit_src",
|
||||
"//src/sksl/codegen:SkSLGLSLCodeGenerator_src",
|
||||
|
@ -445,69 +445,6 @@ bool Analysis::IsTrivialExpression(const Expression& expr) {
|
||||
IsTrivialExpression(*expr.as<IndexExpression>().base()));
|
||||
}
|
||||
|
||||
bool Analysis::IsSameExpressionTree(const Expression& left, const Expression& right) {
|
||||
if (left.kind() != right.kind() || !left.type().matches(right.type())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This isn't a fully exhaustive list of expressions by any stretch of the imagination; for
|
||||
// instance, `x[y+1] = x[y+1]` isn't detected because we don't look at BinaryExpressions.
|
||||
// Since this is intended to be used for optimization purposes, handling the common cases is
|
||||
// sufficient.
|
||||
switch (left.kind()) {
|
||||
case Expression::Kind::kLiteral:
|
||||
return left.as<Literal>().value() == right.as<Literal>().value();
|
||||
|
||||
case Expression::Kind::kConstructorArray:
|
||||
case Expression::Kind::kConstructorArrayCast:
|
||||
case Expression::Kind::kConstructorCompound:
|
||||
case Expression::Kind::kConstructorCompoundCast:
|
||||
case Expression::Kind::kConstructorDiagonalMatrix:
|
||||
case Expression::Kind::kConstructorMatrixResize:
|
||||
case Expression::Kind::kConstructorScalarCast:
|
||||
case Expression::Kind::kConstructorStruct:
|
||||
case Expression::Kind::kConstructorSplat: {
|
||||
if (left.kind() != right.kind()) {
|
||||
return false;
|
||||
}
|
||||
const AnyConstructor& leftCtor = left.asAnyConstructor();
|
||||
const AnyConstructor& rightCtor = right.asAnyConstructor();
|
||||
const auto leftSpan = leftCtor.argumentSpan();
|
||||
const auto rightSpan = rightCtor.argumentSpan();
|
||||
if (leftSpan.size() != rightSpan.size()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t index = 0; index < leftSpan.size(); ++index) {
|
||||
if (!IsSameExpressionTree(*leftSpan[index], *rightSpan[index])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case Expression::Kind::kFieldAccess:
|
||||
return left.as<FieldAccess>().fieldIndex() == right.as<FieldAccess>().fieldIndex() &&
|
||||
IsSameExpressionTree(*left.as<FieldAccess>().base(),
|
||||
*right.as<FieldAccess>().base());
|
||||
|
||||
case Expression::Kind::kIndex:
|
||||
return IsSameExpressionTree(*left.as<IndexExpression>().index(),
|
||||
*right.as<IndexExpression>().index()) &&
|
||||
IsSameExpressionTree(*left.as<IndexExpression>().base(),
|
||||
*right.as<IndexExpression>().base());
|
||||
|
||||
case Expression::Kind::kSwizzle:
|
||||
return left.as<Swizzle>().components() == right.as<Swizzle>().components() &&
|
||||
IsSameExpressionTree(*left.as<Swizzle>().base(), *right.as<Swizzle>().base());
|
||||
|
||||
case Expression::Kind::kVariableReference:
|
||||
return left.as<VariableReference>().variable() ==
|
||||
right.as<VariableReference>().variable();
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class ES2IndexingVisitor : public ProgramVisitor {
|
||||
public:
|
||||
ES2IndexingVisitor(ErrorReporter& errors) : fErrors(errors) {}
|
||||
|
@ -163,3 +163,26 @@ generated_cc_atom(
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = ["//include/sksl:SkSLErrorReporter_hdr"],
|
||||
)
|
||||
|
||||
generated_cc_atom(
|
||||
name = "SkSLIsSameExpressionTree_src",
|
||||
srcs = ["SkSLIsSameExpressionTree.cpp"],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"//include/core:SkSpan_hdr",
|
||||
"//include/core:SkTypes_hdr",
|
||||
"//include/private:SkSLDefines_hdr",
|
||||
"//include/private:SkTArray_hdr",
|
||||
"//include/sksl:SkSLOperator_hdr",
|
||||
"//src/sksl:SkSLAnalysis_hdr",
|
||||
"//src/sksl/ir:SkSLConstructor_hdr",
|
||||
"//src/sksl/ir:SkSLExpression_hdr",
|
||||
"//src/sksl/ir:SkSLFieldAccess_hdr",
|
||||
"//src/sksl/ir:SkSLIndexExpression_hdr",
|
||||
"//src/sksl/ir:SkSLLiteral_hdr",
|
||||
"//src/sksl/ir:SkSLPrefixExpression_hdr",
|
||||
"//src/sksl/ir:SkSLSwizzle_hdr",
|
||||
"//src/sksl/ir:SkSLType_hdr",
|
||||
"//src/sksl/ir:SkSLVariableReference_hdr",
|
||||
],
|
||||
)
|
||||
|
97
src/sksl/analysis/SkSLIsSameExpressionTree.cpp
Normal file
97
src/sksl/analysis/SkSLIsSameExpressionTree.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "include/core/SkSpan.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/private/SkSLDefines.h"
|
||||
#include "include/private/SkTArray.h"
|
||||
#include "include/sksl/SkSLOperator.h"
|
||||
#include "src/sksl/SkSLAnalysis.h"
|
||||
#include "src/sksl/ir/SkSLConstructor.h"
|
||||
#include "src/sksl/ir/SkSLExpression.h"
|
||||
#include "src/sksl/ir/SkSLFieldAccess.h"
|
||||
#include "src/sksl/ir/SkSLIndexExpression.h"
|
||||
#include "src/sksl/ir/SkSLLiteral.h"
|
||||
#include "src/sksl/ir/SkSLPrefixExpression.h"
|
||||
#include "src/sksl/ir/SkSLSwizzle.h"
|
||||
#include "src/sksl/ir/SkSLType.h"
|
||||
#include "src/sksl/ir/SkSLVariableReference.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
bool Analysis::IsSameExpressionTree(const Expression& left, const Expression& right) {
|
||||
if (left.kind() != right.kind() || !left.type().matches(right.type())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This isn't a fully exhaustive list of expressions by any stretch of the imagination; for
|
||||
// instance, `x[y+1] = x[y+1]` isn't detected because we don't look at BinaryExpressions.
|
||||
// Since this is intended to be used for optimization purposes, handling the common cases is
|
||||
// sufficient.
|
||||
switch (left.kind()) {
|
||||
case Expression::Kind::kLiteral:
|
||||
return left.as<Literal>().value() == right.as<Literal>().value();
|
||||
|
||||
case Expression::Kind::kConstructorArray:
|
||||
case Expression::Kind::kConstructorArrayCast:
|
||||
case Expression::Kind::kConstructorCompound:
|
||||
case Expression::Kind::kConstructorCompoundCast:
|
||||
case Expression::Kind::kConstructorDiagonalMatrix:
|
||||
case Expression::Kind::kConstructorMatrixResize:
|
||||
case Expression::Kind::kConstructorScalarCast:
|
||||
case Expression::Kind::kConstructorStruct:
|
||||
case Expression::Kind::kConstructorSplat: {
|
||||
if (left.kind() != right.kind()) {
|
||||
return false;
|
||||
}
|
||||
const AnyConstructor& leftCtor = left.asAnyConstructor();
|
||||
const AnyConstructor& rightCtor = right.asAnyConstructor();
|
||||
const auto leftSpan = leftCtor.argumentSpan();
|
||||
const auto rightSpan = rightCtor.argumentSpan();
|
||||
if (leftSpan.size() != rightSpan.size()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t index = 0; index < leftSpan.size(); ++index) {
|
||||
if (!IsSameExpressionTree(*leftSpan[index], *rightSpan[index])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case Expression::Kind::kFieldAccess:
|
||||
return left.as<FieldAccess>().fieldIndex() == right.as<FieldAccess>().fieldIndex() &&
|
||||
IsSameExpressionTree(*left.as<FieldAccess>().base(),
|
||||
*right.as<FieldAccess>().base());
|
||||
|
||||
case Expression::Kind::kIndex:
|
||||
return IsSameExpressionTree(*left.as<IndexExpression>().index(),
|
||||
*right.as<IndexExpression>().index()) &&
|
||||
IsSameExpressionTree(*left.as<IndexExpression>().base(),
|
||||
*right.as<IndexExpression>().base());
|
||||
|
||||
case Expression::Kind::kPrefix:
|
||||
return (left.as<PrefixExpression>().getOperator().kind() ==
|
||||
right.as<PrefixExpression>().getOperator().kind()) &&
|
||||
IsSameExpressionTree(*left.as<PrefixExpression>().operand(),
|
||||
*right.as<PrefixExpression>().operand());
|
||||
|
||||
case Expression::Kind::kSwizzle:
|
||||
return left.as<Swizzle>().components() == right.as<Swizzle>().components() &&
|
||||
IsSameExpressionTree(*left.as<Swizzle>().base(), *right.as<Swizzle>().base());
|
||||
|
||||
case Expression::Kind::kVariableReference:
|
||||
return left.as<VariableReference>().variable() ==
|
||||
right.as<VariableReference>().variable();
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SkSL
|
@ -23,7 +23,7 @@ vec4 main() {
|
||||
bool _19_r = false;
|
||||
bool _20_s = true;
|
||||
bool _21_t = false;
|
||||
bool _22_u = !_0_a == !_0_a;
|
||||
bool _23_v = !_0_a != !_0_a;
|
||||
bool _22_u = true;
|
||||
bool _23_v = false;
|
||||
return ((((((((((((((((((((_0_a && !_1_b) && _2_c) && !_3_d) && _4_e) && !_5_f) && _6_g) && !_7_h) && _8_i) && !_9_j) && _12_k) && !_13_l) && _14_m) && !_15_n) && _16_o) && !_17_p) && _18_q) && !_19_r) && _20_s) && !_21_t) && _22_u) && !_23_v ? colorGreen : colorRed;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user