Optimize away swizzles of constant variables.

Change-Id: I49807f18ea54e85c2b8f1419278c54aa2d6f8fac
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/402581
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
John Stiles 2021-04-29 11:17:28 -04:00 committed by Skia Commit-Bot
parent 552fcb9a1b
commit 7b253d34ee
3 changed files with 14 additions and 28 deletions

View File

@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
#include "src/sksl/SkSLConstantFolder.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorScalarCast.h"
#include "src/sksl/ir/SkSLConstructorSplat.h"
@ -183,20 +184,24 @@ std::unique_ptr<Expression> Swizzle::Make(const Context& context,
return Swizzle::Make(context, std::move(base.base()), combined);
}
// If we are swizzling a constant expression, we can use its value instead here (so that
// swizzles like `colorWhite.x` can be simplified to `1`).
const Expression* value = ConstantFolder::GetConstantValueForVariable(*expr);
// `half4(scalar).zyy` can be optimized to `half3(scalar)`, and `half3(scalar).y` can be
// optimized to just `scalar`. The swizzle components don't actually matter, as every field
// in a splat constructor holds the same value.
if (expr->is<ConstructorSplat>()) {
ConstructorSplat& splat = expr->as<ConstructorSplat>();
if (value->is<ConstructorSplat>()) {
const ConstructorSplat& splat = value->as<ConstructorSplat>();
return ConstructorSplat::Make(
context, splat.fOffset,
splat.type().componentType().toCompound(context, components.size(), /*rows=*/1),
std::move(splat.argument()));
splat.argument()->clone());
}
// Optimize swizzles of constructors.
if (expr->isAnyConstructor()) {
AnyConstructor& base = expr->asAnyConstructor();
if (value->isAnyConstructor()) {
const AnyConstructor& base = value->asAnyConstructor();
auto baseArguments = base.argumentSpan();
std::unique_ptr<Expression> replacement;
const Type& componentType = exprType.componentType();
@ -299,18 +304,8 @@ std::unique_ptr<Expression> Swizzle::Make(const Context& context,
ExpressionArray newArgs;
newArgs.reserve_back(swizzleSize);
for (const ReorderedArgument& reorderedArg : reorderedArgs) {
std::unique_ptr<Expression>& origArg = baseArguments[reorderedArg.fArgIndex];
// Clone the original argument if there are multiple references to it; just
// steal it if there's only one reference left.
std::unique_ptr<Expression> newArg;
int8_t& exprRemainingRefs = exprUsed[reorderedArg.fArgIndex];
SkASSERT(exprRemainingRefs > 0);
if (--exprRemainingRefs == 0) {
newArg = std::move(origArg);
} else {
newArg = origArg->clone();
}
std::unique_ptr<Expression> newArg =
baseArguments[reorderedArg.fArgIndex]->clone();
if (reorderedArg.fComponents.empty()) {
newArgs.push_back(std::move(newArg));

View File

@ -3,7 +3,7 @@
error: 7: cannot assign to this expression
error: 8: cannot modify immutable variable 'u'
error: 9: cannot modify immutable variable 'x'
error: 11: cannot modify immutable variable 'x'
error: 11: cannot assign to this expression
error: 12: cannot write to the same swizzle field more than once
error: 14: cannot modify immutable variable 'l'
error: 15: cannot modify immutable variable 'r'

View File

@ -3,16 +3,7 @@ out vec4 sk_FragColor;
uniform vec4 colorRed;
uniform vec4 colorGreen;
vec4 main() {
const vec4 _0_colorWhite = vec4(1.0);
const vec2 _1_point = vec2(40.0, 60.0);
bool _2_ok = true;
_2_ok = _2_ok && (((_1_point.x >= 0.0 && _1_point.x <= 100.0) && _1_point.y >= 0.0) && _1_point.y <= 100.0);
_2_ok = _2_ok && _0_colorWhite.x == 1.0;
_2_ok = _2_ok && _0_colorWhite.x + _0_colorWhite.y == 2.0;
_2_ok = _2_ok && (_0_colorWhite.x + _0_colorWhite.y) + _0_colorWhite.z == 3.0;
_2_ok = _2_ok && ((_0_colorWhite.x + _0_colorWhite.y) + _0_colorWhite.z) + _0_colorWhite.w == 4.0;
_2_ok = _2_ok && colorGreen * _0_colorWhite.x != colorRed * _0_colorWhite.y;
const vec2 _3_pointOffset = _1_point.yx + _0_colorWhite.xz;
_2_ok = _2_ok && _3_pointOffset == vec2(61.0, 41.0);
_2_ok = _2_ok && colorGreen != colorRed;
return _2_ok ? colorGreen : colorRed;
}