Simplify constructors at IR generation time.
This performs the same simplifications as the control-flow phase, but at IR generation time. There's no visible difference in the tests (besides DSL) because these aren't new optimizations; they're just happening at a different phase of compilation. Change-Id: I26d241167b0e690b23f8f4370339714783c8d6fd Bug: skia:11343 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/371482 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>
This commit is contained in:
parent
0404933136
commit
b9e4f649b4
@ -892,6 +892,9 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
|
||||
break;
|
||||
}
|
||||
case Expression::Kind::kConstructor: {
|
||||
// TODO(skia:11319): this optimization logic is redundant with the optimization code
|
||||
// found in SkSLConstructor.cpp.
|
||||
|
||||
// Find constructors embedded inside constructors and flatten them out where possible.
|
||||
// - float4(float2(1, 2), 3, 4) --> float4(1, 2, 3, 4)
|
||||
// - float4(w, float3(sin(x), cos(y), tan(z))) --> float4(w, sin(x), cos(y), tan(z))
|
||||
|
@ -129,6 +129,47 @@ std::unique_ptr<Expression> Constructor::MakeCompoundConstructor(const Context&
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (context.fConfig->fSettings.fOptimize) {
|
||||
// Find constructors embedded inside constructors and flatten them out where possible.
|
||||
// - float4(float2(1, 2), 3, 4) --> float4(1, 2, 3, 4)
|
||||
// - float4(w, float3(sin(x), cos(y), tan(z))) --> float4(w, sin(x), cos(y), tan(z))
|
||||
|
||||
// Inspect each constructor argument to see if it's a candidate for flattening.
|
||||
// Remember matched arguments in a bitfield, "argsToOptimize".
|
||||
int argsToOptimize = 0;
|
||||
int currBit = 1;
|
||||
for (const std::unique_ptr<Expression>& arg : args) {
|
||||
if (arg->is<Constructor>()) {
|
||||
Constructor& inner = arg->as<Constructor>();
|
||||
if (inner.arguments().size() > 1 &&
|
||||
inner.type().componentType() == type.componentType()) {
|
||||
argsToOptimize |= currBit;
|
||||
}
|
||||
}
|
||||
currBit <<= 1;
|
||||
}
|
||||
|
||||
if (argsToOptimize) {
|
||||
// We found at least one argument that could be flattened out. Re-walk the constructor
|
||||
// args and flatten the candidates we found during our initial pass.
|
||||
ExpressionArray flattened;
|
||||
flattened.reserve_back(type.columns());
|
||||
currBit = 1;
|
||||
for (std::unique_ptr<Expression>& arg : args) {
|
||||
if (argsToOptimize & currBit) {
|
||||
Constructor& inner = arg->as<Constructor>();
|
||||
for (std::unique_ptr<Expression>& innerArg : inner.arguments()) {
|
||||
flattened.push_back(std::move(innerArg));
|
||||
}
|
||||
} else {
|
||||
flattened.push_back(std::move(arg));
|
||||
}
|
||||
currBit <<= 1;
|
||||
}
|
||||
args = std::move(flattened);
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_unique<Constructor>(offset, type, std::move(args));
|
||||
}
|
||||
|
||||
|
@ -136,15 +136,15 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLFloat, r, ctxInfo) {
|
||||
EXPECT_EQUAL(Float3(0.75),
|
||||
"float3(0.75)");
|
||||
EXPECT_EQUAL(Float3(Float2(0, 1), -2),
|
||||
"float3(float2(0.0, 1.0), -2.0)");
|
||||
"float3(0.0, 1.0, -2.0)");
|
||||
EXPECT_EQUAL(Float3(0, 1, 2),
|
||||
"float3(0.0, 1.0, 2.0)");
|
||||
EXPECT_EQUAL(Float4(0),
|
||||
"float4(0.0)");
|
||||
EXPECT_EQUAL(Float4(Float2(0, 1), Float2(2, 3)),
|
||||
"float4(float2(0.0, 1.0), float2(2.0, 3.0))");
|
||||
"float4(0.0, 1.0, 2.0, 3.0)");
|
||||
EXPECT_EQUAL(Float4(0, 1, Float2(2, 3)),
|
||||
"float4(0.0, 1.0, float2(2.0, 3.0))");
|
||||
"float4(0.0, 1.0, 2.0, 3.0)");
|
||||
EXPECT_EQUAL(Float4(0, 1, 2, 3),
|
||||
"float4(0.0, 1.0, 2.0, 3.0)");
|
||||
|
||||
@ -181,32 +181,24 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLHalf, r, ctxInfo) {
|
||||
REPORTER_ASSERT(r,
|
||||
atof(e2.release()->description().c_str()) == std::numeric_limits<float>::min());
|
||||
|
||||
Expression e3 = Half2(0);
|
||||
EXPECT_EQUAL(e3, "half2(0.0)");
|
||||
|
||||
Expression e4 = Half2(-0.5, 1);
|
||||
EXPECT_EQUAL(e4, "half2(-0.5, 1.0)");
|
||||
|
||||
Expression e5 = Half3(0.75);
|
||||
EXPECT_EQUAL(e5, "half3(0.75)");
|
||||
|
||||
Expression e6 = Half3(Half2(0, 1), -2);
|
||||
EXPECT_EQUAL(e6, "half3(half2(0.0, 1.0), -2.0)");
|
||||
|
||||
Expression e7 = Half3(0, 1, 2);
|
||||
EXPECT_EQUAL(e7, "half3(0.0, 1.0, 2.0)");
|
||||
|
||||
Expression e8 = Half4(0);
|
||||
EXPECT_EQUAL(e8, "half4(0.0)");
|
||||
|
||||
Expression e9 = Half4(Half2(0, 1), Half2(2, 3));
|
||||
EXPECT_EQUAL(e9, "half4(half2(0.0, 1.0), half2(2.0, 3.0))");
|
||||
|
||||
Expression e10 = Half4(0, 1, Half2(2, 3));
|
||||
EXPECT_EQUAL(e10, "half4(0.0, 1.0, half2(2.0, 3.0))");
|
||||
|
||||
Expression e11 = Half4(0, 1, 2, 3);
|
||||
EXPECT_EQUAL(e11, "half4(0.0, 1.0, 2.0, 3.0)");
|
||||
EXPECT_EQUAL(Half2(0),
|
||||
"half2(0.0)");
|
||||
EXPECT_EQUAL(Half2(-0.5, 1),
|
||||
"half2(-0.5, 1.0)");
|
||||
EXPECT_EQUAL(Half3(0.75),
|
||||
"half3(0.75)");
|
||||
EXPECT_EQUAL(Half3(Half2(0, 1), -2),
|
||||
"half3(0.0, 1.0, -2.0)");
|
||||
EXPECT_EQUAL(Half3(0, 1, 2),
|
||||
"half3(0.0, 1.0, 2.0)");
|
||||
EXPECT_EQUAL(Half4(0),
|
||||
"half4(0.0)");
|
||||
EXPECT_EQUAL(Half4(Half2(0, 1), Half2(2, 3)),
|
||||
"half4(0.0, 1.0, 2.0, 3.0)");
|
||||
EXPECT_EQUAL(Half4(0, 1, Half2(2, 3)),
|
||||
"half4(0.0, 1.0, 2.0, 3.0)");
|
||||
EXPECT_EQUAL(Half4(0, 1, 2, 3),
|
||||
"half4(0.0, 1.0, 2.0, 3.0)");
|
||||
|
||||
{
|
||||
ExpectError error(r, "error: floating point value is infinite\n");
|
||||
@ -233,35 +225,27 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLHalf, r, ctxInfo) {
|
||||
|
||||
DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLInt, r, ctxInfo) {
|
||||
AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
|
||||
Expression e1 = Int(std::numeric_limits<int32_t>::max());
|
||||
EXPECT_EQUAL(e1, "2147483647");
|
||||
|
||||
Expression e2 = Int2(std::numeric_limits<int32_t>::min());
|
||||
EXPECT_EQUAL(e2, "int2(-2147483648)");
|
||||
|
||||
Expression e3 = Int2(0, 1);
|
||||
EXPECT_EQUAL(e3, "int2(0, 1)");
|
||||
|
||||
Expression e4 = Int3(0);
|
||||
EXPECT_EQUAL(e4, "int3(0)");
|
||||
|
||||
Expression e5 = Int3(Int2(0, 1), -2);
|
||||
EXPECT_EQUAL(e5, "int3(int2(0, 1), -2)");
|
||||
|
||||
Expression e6 = Int3(0, 1, 2);
|
||||
EXPECT_EQUAL(e6, "int3(0, 1, 2)");
|
||||
|
||||
Expression e7 = Int4(0);
|
||||
EXPECT_EQUAL(e7, "int4(0)");
|
||||
|
||||
Expression e8 = Int4(Int2(0, 1), Int2(2, 3));
|
||||
EXPECT_EQUAL(e8, "int4(int2(0, 1), int2(2, 3))");
|
||||
|
||||
Expression e9 = Int4(0, 1, Int2(2, 3));
|
||||
EXPECT_EQUAL(e9, "int4(0, 1, int2(2, 3))");
|
||||
|
||||
Expression e10 = Int4(0, 1, 2, 3);
|
||||
EXPECT_EQUAL(e10, "int4(0, 1, 2, 3)");
|
||||
EXPECT_EQUAL(Int(std::numeric_limits<int32_t>::max()),
|
||||
"2147483647");
|
||||
EXPECT_EQUAL(Int2(std::numeric_limits<int32_t>::min()),
|
||||
"int2(-2147483648)");
|
||||
EXPECT_EQUAL(Int2(0, 1),
|
||||
"int2(0, 1)");
|
||||
EXPECT_EQUAL(Int3(0),
|
||||
"int3(0)");
|
||||
EXPECT_EQUAL(Int3(Int2(0, 1), -2),
|
||||
"int3(0, 1, -2)");
|
||||
EXPECT_EQUAL(Int3(0, 1, 2),
|
||||
"int3(0, 1, 2)");
|
||||
EXPECT_EQUAL(Int4(0),
|
||||
"int4(0)");
|
||||
EXPECT_EQUAL(Int4(Int2(0, 1), Int2(2, 3)),
|
||||
"int4(0, 1, 2, 3)");
|
||||
EXPECT_EQUAL(Int4(0, 1, Int2(2, 3)),
|
||||
"int4(0, 1, 2, 3)");
|
||||
EXPECT_EQUAL(Int4(0, 1, 2, 3),
|
||||
"int4(0, 1, 2, 3)");
|
||||
|
||||
{
|
||||
ExpectError error(r, "error: invalid arguments to 'int2' constructor (expected 2 scalars,"
|
||||
@ -278,35 +262,27 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLInt, r, ctxInfo) {
|
||||
|
||||
DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLShort, r, ctxInfo) {
|
||||
AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
|
||||
Expression e1 = Short(std::numeric_limits<int16_t>::max());
|
||||
EXPECT_EQUAL(e1, "32767");
|
||||
|
||||
Expression e2 = Short2(std::numeric_limits<int16_t>::min());
|
||||
EXPECT_EQUAL(e2, "short2(-32768)");
|
||||
|
||||
Expression e3 = Short2(0, 1);
|
||||
EXPECT_EQUAL(e3, "short2(0, 1)");
|
||||
|
||||
Expression e4 = Short3(0);
|
||||
EXPECT_EQUAL(e4, "short3(0)");
|
||||
|
||||
Expression e5 = Short3(Short2(0, 1), -2);
|
||||
EXPECT_EQUAL(e5, "short3(short2(0, 1), -2)");
|
||||
|
||||
Expression e6 = Short3(0, 1, 2);
|
||||
EXPECT_EQUAL(e6, "short3(0, 1, 2)");
|
||||
|
||||
Expression e7 = Short4(0);
|
||||
EXPECT_EQUAL(e7, "short4(0)");
|
||||
|
||||
Expression e8 = Short4(Short2(0, 1), Short2(2, 3));
|
||||
EXPECT_EQUAL(e8, "short4(short2(0, 1), short2(2, 3))");
|
||||
|
||||
Expression e9 = Short4(0, 1, Short2(2, 3));
|
||||
EXPECT_EQUAL(e9, "short4(0, 1, short2(2, 3))");
|
||||
|
||||
Expression e10 = Short4(0, 1, 2, 3);
|
||||
EXPECT_EQUAL(e10, "short4(0, 1, 2, 3)");
|
||||
EXPECT_EQUAL(Short(std::numeric_limits<int16_t>::max()),
|
||||
"32767");
|
||||
EXPECT_EQUAL(Short2(std::numeric_limits<int16_t>::min()),
|
||||
"short2(-32768)");
|
||||
EXPECT_EQUAL(Short2(0, 1),
|
||||
"short2(0, 1)");
|
||||
EXPECT_EQUAL(Short3(0),
|
||||
"short3(0)");
|
||||
EXPECT_EQUAL(Short3(Short2(0, 1), -2),
|
||||
"short3(0, 1, -2)");
|
||||
EXPECT_EQUAL(Short3(0, 1, 2),
|
||||
"short3(0, 1, 2)");
|
||||
EXPECT_EQUAL(Short4(0),
|
||||
"short4(0)");
|
||||
EXPECT_EQUAL(Short4(Short2(0, 1), Short2(2, 3)),
|
||||
"short4(0, 1, 2, 3)");
|
||||
EXPECT_EQUAL(Short4(0, 1, Short2(2, 3)),
|
||||
"short4(0, 1, 2, 3)");
|
||||
EXPECT_EQUAL(Short4(0, 1, 2, 3),
|
||||
"short4(0, 1, 2, 3)");
|
||||
|
||||
{
|
||||
ExpectError error(r, "error: invalid arguments to 'short2' constructor (expected 2 scalars,"
|
||||
@ -323,33 +299,25 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLShort, r, ctxInfo) {
|
||||
|
||||
DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLBool, r, ctxInfo) {
|
||||
AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
|
||||
Expression e1 = Bool2(false);
|
||||
EXPECT_EQUAL(e1, "bool2(false)");
|
||||
|
||||
Expression e2 = Bool2(false, true);
|
||||
EXPECT_EQUAL(e2, "bool2(false, true)");
|
||||
|
||||
Expression e3 = Bool3(false);
|
||||
EXPECT_EQUAL(e3, "bool3(false)");
|
||||
|
||||
Expression e4 = Bool3(Bool2(false, true), false);
|
||||
EXPECT_EQUAL(e4, "bool3(bool2(false, true), false)");
|
||||
|
||||
Expression e5 = Bool3(false, true, false);
|
||||
EXPECT_EQUAL(e5, "bool3(false, true, false)");
|
||||
|
||||
Expression e6 = Bool4(false);
|
||||
EXPECT_EQUAL(e6, "bool4(false)");
|
||||
|
||||
Expression e7 = Bool4(Bool2(false, true), Bool2(false, true));
|
||||
EXPECT_EQUAL(e7, "bool4(bool2(false, true), "
|
||||
"bool2(false, true))");
|
||||
|
||||
Expression e8 = Bool4(false, true, Bool2(false, true));
|
||||
EXPECT_EQUAL(e8, "bool4(false, true, bool2(false, true))");
|
||||
|
||||
Expression e9 = Bool4(false, true, false, true);
|
||||
EXPECT_EQUAL(e9, "bool4(false, true, false, true)");
|
||||
EXPECT_EQUAL(Bool2(false),
|
||||
"bool2(false)");
|
||||
EXPECT_EQUAL(Bool2(false, true),
|
||||
"bool2(false, true)");
|
||||
EXPECT_EQUAL(Bool3(false),
|
||||
"bool3(false)");
|
||||
EXPECT_EQUAL(Bool3(Bool2(false, true), false),
|
||||
"bool3(false, true, false)");
|
||||
EXPECT_EQUAL(Bool3(false, true, false),
|
||||
"bool3(false, true, false)");
|
||||
EXPECT_EQUAL(Bool4(false),
|
||||
"bool4(false)");
|
||||
EXPECT_EQUAL(Bool4(Bool2(false, true), Bool2(false, true)),
|
||||
"bool4(false, true, false, true)");
|
||||
EXPECT_EQUAL(Bool4(false, true, Bool2(false, true)),
|
||||
"bool4(false, true, false, true)");
|
||||
EXPECT_EQUAL(Bool4(false, true, false, true),
|
||||
"bool4(false, true, false, true)");
|
||||
|
||||
{
|
||||
ExpectError error(r, "error: invalid arguments to 'bool2' constructor (expected 2 scalars,"
|
||||
|
Loading…
Reference in New Issue
Block a user