Commit ea78d2bb by Olli Etuaho Committed by Commit Bot

Prune unreferenced variables with a constructor initializer

Treat aggregate constructors as having no side effects, which enables pruning declarators that have a constructor initializer. Some logic in RemoveUnreferencedVariables is fixed to make this work correctly for structs. The bugs were previously not exposed since constructors were treated as having side effects, but now that those can be pruned the logic needs to be correct. BUG=angleproject:2298 TEST=angle_unittests Change-Id: I6fbe61a9e82065196baa29c200bf556fc21d8962 Reviewed-on: https://chromium-review.googlesource.com/856499Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 0e1224c8
...@@ -522,7 +522,13 @@ const char *TIntermAggregate::functionName() const ...@@ -522,7 +522,13 @@ const char *TIntermAggregate::functionName() const
bool TIntermAggregate::hasSideEffects() const bool TIntermAggregate::hasSideEffects() const
{ {
if (isFunctionCall() && mFunction != nullptr && mFunction->isKnownToNotHaveSideEffects()) if (getQualifier() == EvqConst)
{
return false;
}
bool calledFunctionHasNoSideEffects =
isFunctionCall() && mFunction != nullptr && mFunction->isKnownToNotHaveSideEffects();
if (calledFunctionHasNoSideEffects || isConstructor())
{ {
for (TIntermNode *arg : mArguments) for (TIntermNode *arg : mArguments)
{ {
......
...@@ -177,7 +177,17 @@ void RemoveUnreferencedVariablesTraverser::removeVariableDeclaration(TIntermDecl ...@@ -177,7 +177,17 @@ void RemoveUnreferencedVariablesTraverser::removeVariableDeclaration(TIntermDecl
if (declarator->getType().isStructSpecifier() && !declarator->getType().isNamelessStruct()) if (declarator->getType().isStructSpecifier() && !declarator->getType().isNamelessStruct())
{ {
unsigned int structId = declarator->getType().getStruct()->uniqueId().get(); unsigned int structId = declarator->getType().getStruct()->uniqueId().get();
if ((*mStructIdRefCounts)[structId] > 1u) unsigned int structRefCountInThisDeclarator = 1u;
if (declarator->getAsBinaryNode() &&
declarator->getAsBinaryNode()->getRight()->getAsAggregate())
{
ASSERT(declarator->getAsBinaryNode()->getLeft()->getType().getStruct() ==
declarator->getType().getStruct());
ASSERT(declarator->getAsBinaryNode()->getRight()->getType().getStruct() ==
declarator->getType().getStruct());
structRefCountInThisDeclarator = 2u;
}
if ((*mStructIdRefCounts)[structId] > structRefCountInThisDeclarator)
{ {
// If this declaration declares a named struct type that is used elsewhere, we need to // If this declaration declares a named struct type that is used elsewhere, we need to
// keep it. We can still change the declarator though so that it doesn't declare an // keep it. We can still change the declarator though so that it doesn't declare an
...@@ -272,7 +282,7 @@ void RemoveUnreferencedVariablesTraverser::visitSymbol(TIntermSymbol *node) ...@@ -272,7 +282,7 @@ void RemoveUnreferencedVariablesTraverser::visitSymbol(TIntermSymbol *node)
bool RemoveUnreferencedVariablesTraverser::visitAggregate(Visit visit, TIntermAggregate *node) bool RemoveUnreferencedVariablesTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{ {
if (mRemoveReferences) if (visit == PreVisit && mRemoveReferences)
{ {
decrementStructTypeRefCount(node->getType()); decrementStructTypeRefCount(node->getType());
} }
......
...@@ -175,7 +175,7 @@ TEST_F(ConstantFoldingTest, Fold3x3MatrixInverse) ...@@ -175,7 +175,7 @@ TEST_F(ConstantFoldingTest, Fold3x3MatrixInverse)
" 23.0f, 29.0f, 31.0f,\n" " 23.0f, 29.0f, 31.0f,\n"
" 37.0f, 41.0f, 43.0f));\n" " 37.0f, 41.0f, 43.0f));\n"
" mat3 m = m3 * mat3(i);\n" " mat3 m = m3 * mat3(i);\n"
" my_Vec = m3[0];\n" " my_Vec = m[0];\n"
"}\n"; "}\n";
compileAssumeSuccess(shaderString); compileAssumeSuccess(shaderString);
float inputElements[] = float inputElements[] =
......
...@@ -686,3 +686,29 @@ TEST_F(RemoveUnreferencedVariablesTest, UserDefinedTypeInUniformBlock) ...@@ -686,3 +686,29 @@ TEST_F(RemoveUnreferencedVariablesTest, UserDefinedTypeInUniformBlock)
ASSERT_TRUE(foundInCode("struct _umyStructType")); ASSERT_TRUE(foundInCode("struct _umyStructType"));
} }
// Test that a struct type that is referenced from an initializer with a constructor can be removed.
TEST_F(RemoveUnreferencedVariablesTest, UserDefinedTypeConstructorInitializer)
{
const std::string &shaderString =
R"(#version 300 es
precision highp float;
out vec4 my_FragColor;
struct myStructType
{
int iMember;
};
uniform int ui;
void main()
{
myStructType S = myStructType(ui);
my_FragColor = vec4(0, 1, 0, 1);
})";
compile(shaderString);
ASSERT_TRUE(notFoundInCode("myStructType"));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment