Avoid creating temporary variables for nested trivial cases.

For instance, `foo[0].x` is now considered trivial to inline. It
combines two trivial cases: array-indexing by an int literal, and a
swizzle.

Change-Id: Ibb3ca1f324bbee0e9b3556e66644923fc9e0cf45
Bug: skia:10786
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/320768
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2020-09-29 17:42:23 -04:00 committed by Skia Commit-Bot
parent dd33b3ea90
commit 44733aa1e2
3 changed files with 23 additions and 13 deletions

View File

@ -243,6 +243,15 @@ std::unique_ptr<Expression> clone_with_ref_kind(const Expression& expr,
return clone;
}
bool is_trivial_argument(const Expression& argument) {
return argument.is<VariableReference>() ||
(argument.is<Swizzle>() && is_trivial_argument(*argument.as<Swizzle>().fBase)) ||
(argument.is<FieldAccess>() && is_trivial_argument(*argument.as<FieldAccess>().fBase)) ||
(argument.is<IndexExpression>() &&
argument.as<IndexExpression>().fIndex->is<IntLiteral>() &&
is_trivial_argument(*argument.as<IndexExpression>().fBase));
}
} // namespace
void Inliner::ensureScopedBlocks(Statement* inlinedBody, Statement* parentStmt) {
@ -661,15 +670,8 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
const Variable* param = function.fDeclaration.fParameters[i];
bool isOutParam = param->fModifiers.fFlags & Modifiers::kOut_Flag;
// If this is a variable, a swizzled variable, a struct member, or a simple array access...
if (arguments[i]->is<VariableReference>() ||
(arguments[i]->is<Swizzle>() &&
arguments[i]->as<Swizzle>().fBase->is<VariableReference>()) ||
(arguments[i]->is<FieldAccess>() &&
arguments[i]->as<FieldAccess>().fBase->is<VariableReference>()) ||
(arguments[i]->is<IndexExpression>() &&
arguments[i]->as<IndexExpression>().fBase->is<VariableReference>() &&
arguments[i]->as<IndexExpression>().fIndex->is<IntLiteral>())) {
// If this argument can be inlined trivially (e.g. a swizzle, or a constant array index)...
if (is_trivial_argument(*arguments[i])) {
// ... and it's an `out` param, or it isn't written to within the inline function...
if (isOutParam || !Analysis::StatementWritesToVariable(*function.fBody, *param)) {
// ... we don't need to copy it at all! We can just use the existing expression.

View File

@ -41,7 +41,9 @@ void main() {
}
h4x4[3].w = 1.0;
{
h4x4[3].w = 1.0;
}
sk_FragColor = vec4(mat2(2.0)[0][0], h3x3[0][0], h4x4[0][0], 1.0);
@ -75,7 +77,9 @@ void main() {
}
f2x2[0][0] = 1.0;
{
f2x2[0][0] = 1.0;
}
sk_FragColor = vec4(f2x2[0][0], mat3(3.0)[0][0], mat4(4.0)[0][0], 1.0);

View File

@ -49,7 +49,9 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
}
h4x4[3].w = 1.0;
{
h4x4[3].w = 1.0;
}
_out->sk_FragColor = float4(float2x2(2.0)[0][0], h3x3[0][0], h4x4[0][0], 1.0);
@ -83,7 +85,9 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
}
f2x2[0][0] = 1.0;
{
f2x2[0][0] = 1.0;
}
_out->sk_FragColor = float4(f2x2[0][0], float3x3(3.0)[0][0], float4x4(4.0)[0][0], 1.0);