Improve constant folding for boolean vectors.
The additional tests from http://review.skia.org/441238 uncovered a gap
in the constant folder's abilities; it was not able to fold away
boolean vector comparisons even when they were constant. These are ES2
constant-expressions, so folding them properly is a requirement.
Change-Id: Ia0b4d5d1215c5fc2b247ac3f0dec4c8747d2153e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/441579
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/resources/sksl/folding/BoolFolding.sksl b/resources/sksl/folding/BoolFolding.sksl
index d2a3073..5bd19ba 100644
--- a/resources/sksl/folding/BoolFolding.sksl
+++ b/resources/sksl/folding/BoolFolding.sksl
@@ -21,7 +21,13 @@
bool o = any(not(bool2(0 == 1, FALSE))); // all true
bool p = all(not(bool4(1 == 1, !false, 123 > 12, TRUE))); // none are true
- return a && !b && c && !d && e && !f && g && !h && i && !j && k && !l && m && !n && o && !p;
+ bool q = bool4(true) == bool4(true, true, true, true);
+ bool r = bool4(true) == bool4(true, false, true, true);
+ bool s = bool4(true, true, true, true) == bool4(true);
+ bool t = bool4(true, true, true, false) == bool4(true);
+
+ return a && !b && c && !d && e && !f && g && !h && i && !j && k && !l && m && !n && o && !p
+ && q && !r && s && !t;
}
half4 main(float2 coords) {
diff --git a/src/sksl/SkSLConstantFolder.cpp b/src/sksl/SkSLConstantFolder.cpp
index bff7bd8..295ec2a 100644
--- a/src/sksl/SkSLConstantFolder.cpp
+++ b/src/sksl/SkSLConstantFolder.cpp
@@ -63,6 +63,28 @@
return eliminate_no_op_boolean(right, op, left);
}
+static std::unique_ptr<Expression> simplify_vector_equality(const Context& context,
+ const Expression& left,
+ Operator op,
+ const Expression& right) {
+ if (op.kind() == Token::Kind::TK_EQEQ || op.kind() == Token::Kind::TK_NEQ) {
+ bool equality = (op.kind() == Token::Kind::TK_EQEQ);
+
+ switch (left.compareConstant(right)) {
+ case Expression::ComparisonResult::kNotEqual:
+ equality = !equality;
+ [[fallthrough]];
+
+ case Expression::ComparisonResult::kEqual:
+ return BoolLiteral::Make(context, left.fOffset, equality);
+
+ case Expression::ComparisonResult::kUnknown:
+ break;
+ }
+ }
+ return nullptr;
+}
+
// 'T' is the actual stored type of the literal data (SKSL_FLOAT or SKSL_INT).
// 'U' is an unsigned version of that, used to perform addition, subtraction, and multiplication,
// to avoid signed-integer overflow errors. This mimics the use of URESULT vs. RESULT when doing
@@ -76,21 +98,9 @@
SkASSERT(left.type() == right.type());
const Type& type = left.type();
- // Handle boolean operations: == !=
- if (op.kind() == Token::Kind::TK_EQEQ || op.kind() == Token::Kind::TK_NEQ) {
- bool equality = (op.kind() == Token::Kind::TK_EQEQ);
-
- switch (left.compareConstant(right)) {
- case Expression::ComparisonResult::kNotEqual:
- equality = !equality;
- [[fallthrough]];
-
- case Expression::ComparisonResult::kEqual:
- return BoolLiteral::Make(context, left.fOffset, equality);
-
- case Expression::ComparisonResult::kUnknown:
- return nullptr;
- }
+ // Handle equality operations: == !=
+ if (std::unique_ptr<Expression> result = simplify_vector_equality(context, left, op, right)) {
+ return result;
}
// Handle floating-point arithmetic: + - * /
@@ -522,6 +532,9 @@
if (leftType.componentType().isInteger()) {
return simplify_vector<SKSL_INT, SKSL_UINT>(context, *left, op, *right);
}
+ if (leftType.componentType().isBoolean()) {
+ return simplify_vector_equality(context, *left, op, *right);
+ }
return nullptr;
}
@@ -535,6 +548,10 @@
return simplify_vector<SKSL_INT, SKSL_UINT>(context, *left, op,
splat_scalar(*right, left->type()));
}
+ if (rightType.isBoolean()) {
+ return simplify_vector_equality(context, *left, op,
+ splat_scalar(*right, left->type()));
+ }
return nullptr;
}
@@ -548,6 +565,10 @@
return simplify_vector<SKSL_INT, SKSL_UINT>(context, splat_scalar(*left, right->type()),
op, *right);
}
+ if (leftType.isBoolean()) {
+ return simplify_vector_equality(context, splat_scalar(*left, right->type()),
+ op, *right);
+ }
return nullptr;
}
diff --git a/tests/sksl/folding/BoolFolding.glsl b/tests/sksl/folding/BoolFolding.glsl
index 6aea1a5..ff382db 100644
--- a/tests/sksl/folding/BoolFolding.glsl
+++ b/tests/sksl/folding/BoolFolding.glsl
@@ -19,5 +19,9 @@
bool _15_n = false;
bool _16_o = true;
bool _17_p = 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 ? colorGreen : colorRed;
+ bool _18_q = true;
+ bool _19_r = false;
+ bool _20_s = true;
+ bool _21_t = 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 ? colorGreen : colorRed;
}
diff --git a/tests/sksl/shared/MatrixToVectorCast.asm.frag b/tests/sksl/shared/MatrixToVectorCast.asm.frag
index 3825e71..f99d0d2 100644
--- a/tests/sksl/shared/MatrixToVectorCast.asm.frag
+++ b/tests/sksl/shared/MatrixToVectorCast.asm.frag
@@ -65,10 +65,9 @@
OpDecorate %107 RelaxedPrecision
OpDecorate %109 RelaxedPrecision
OpDecorate %116 RelaxedPrecision
-OpDecorate %122 RelaxedPrecision
-OpDecorate %131 RelaxedPrecision
-OpDecorate %133 RelaxedPrecision
-OpDecorate %134 RelaxedPrecision
+OpDecorate %125 RelaxedPrecision
+OpDecorate %127 RelaxedPrecision
+OpDecorate %128 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -120,7 +119,7 @@
%25 = OpFunctionParameter %_ptr_Function_v2float
%26 = OpLabel
%ok = OpVariable %_ptr_Function_bool Function
-%123 = OpVariable %_ptr_Function_v4float Function
+%117 = OpVariable %_ptr_Function_v4float Function
OpStore %ok %true
%31 = OpLoad %bool %ok
OpSelectionMerge %33 None
@@ -209,29 +208,19 @@
%115 = OpPhi %bool %false %68 %114 %94
OpStore %ok %115
%116 = OpLoad %bool %ok
-OpSelectionMerge %118 None
-OpBranchConditional %116 %117 %118
-%117 = OpLabel
-%119 = OpLogicalEqual %v4bool %112 %112
-%120 = OpAll %bool %119
-OpBranch %118
-%118 = OpLabel
-%121 = OpPhi %bool %false %95 %120 %117
-OpStore %ok %121
-%122 = OpLoad %bool %ok
-OpSelectionMerge %127 None
-OpBranchConditional %122 %125 %126
-%125 = OpLabel
-%128 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
-%131 = OpLoad %v4float %128
-OpStore %123 %131
-OpBranch %127
-%126 = OpLabel
-%132 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
-%133 = OpLoad %v4float %132
-OpStore %123 %133
-OpBranch %127
-%127 = OpLabel
-%134 = OpLoad %v4float %123
-OpReturnValue %134
+OpSelectionMerge %121 None
+OpBranchConditional %116 %119 %120
+%119 = OpLabel
+%122 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%125 = OpLoad %v4float %122
+OpStore %117 %125
+OpBranch %121
+%120 = OpLabel
+%126 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%127 = OpLoad %v4float %126
+OpStore %117 %127
+OpBranch %121
+%121 = OpLabel
+%128 = OpLoad %v4float %117
+OpReturnValue %128
OpFunctionEnd
diff --git a/tests/sksl/shared/MatrixToVectorCast.glsl b/tests/sksl/shared/MatrixToVectorCast.glsl
index 7a4504a..0a382d9 100644
--- a/tests/sksl/shared/MatrixToVectorCast.glsl
+++ b/tests/sksl/shared/MatrixToVectorCast.glsl
@@ -9,6 +9,5 @@
ok = ok && vec4(testMatrix2x2) == vec4(1.0, 2.0, 3.0, 4.0);
ok = ok && ivec4(vec4(testMatrix2x2)) == ivec4(1, 2, 3, 4);
ok = ok && bvec4(vec4(testMatrix2x2)) == bvec4(true, true, true, true);
- ok = ok && bvec4(true, true, true, true) == bvec4(true);
return ok ? colorGreen : colorRed;
}
diff --git a/tests/sksl/shared/MatrixToVectorCast.metal b/tests/sksl/shared/MatrixToVectorCast.metal
index e2586d2..8a681dd 100644
--- a/tests/sksl/shared/MatrixToVectorCast.metal
+++ b/tests/sksl/shared/MatrixToVectorCast.metal
@@ -23,7 +23,6 @@
ok = ok && all(float4_from_float2x2(_uniforms.testMatrix2x2) == float4(1.0, 2.0, 3.0, 4.0));
ok = ok && all(int4(float4_from_float2x2(_uniforms.testMatrix2x2)) == int4(1, 2, 3, 4));
ok = ok && all(bool4(float4_from_float2x2(_uniforms.testMatrix2x2)) == bool4(true, true, true, true));
- ok = ok && all(bool4(true, true, true, true) == bool4(true));
_out.sk_FragColor = ok ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}