summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp358
1 files changed, 0 insertions, 358 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp
deleted file mode 100644
index 74b5e73f71..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp
+++ /dev/null
@@ -1,358 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// RemoveUnreferencedVariables.cpp:
-// Drop variables that are declared but never referenced in the AST. This avoids adding unnecessary
-// initialization code for them. Also removes unreferenced struct types.
-//
-
-#include "compiler/translator/RemoveUnreferencedVariables.h"
-
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class CollectVariableRefCountsTraverser : public TIntermTraverser
-{
- public:
- CollectVariableRefCountsTraverser();
-
- using RefCountMap = std::unordered_map<int, unsigned int>;
- RefCountMap &getSymbolIdRefCounts() { return mSymbolIdRefCounts; }
- RefCountMap &getStructIdRefCounts() { return mStructIdRefCounts; }
-
- void visitSymbol(TIntermSymbol *node) override;
- bool visitAggregate(Visit visit, TIntermAggregate *node) override;
- bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
-
- private:
- void incrementStructTypeRefCount(const TType &type);
-
- RefCountMap mSymbolIdRefCounts;
-
- // Structure reference counts are counted from symbols, constructors, function calls, function
- // return values and from interface block and structure fields. We need to track both function
- // calls and function return values since there's a compiler option not to prune unused
- // functions. The type of a constant union may also be a struct, but statements that are just a
- // constant union are always pruned, and if the constant union is used somehow it will get
- // counted by something else.
- RefCountMap mStructIdRefCounts;
-};
-
-CollectVariableRefCountsTraverser::CollectVariableRefCountsTraverser()
- : TIntermTraverser(true, false, false)
-{
-}
-
-void CollectVariableRefCountsTraverser::incrementStructTypeRefCount(const TType &type)
-{
- if (type.isInterfaceBlock())
- {
- const auto *block = type.getInterfaceBlock();
- ASSERT(block);
-
- // We can end up incrementing ref counts of struct types referenced from an interface block
- // multiple times for the same block. This doesn't matter, because interface blocks can't be
- // pruned so we'll never do the reverse operation.
- for (const auto &field : block->fields())
- {
- ASSERT(!field->type()->isInterfaceBlock());
- incrementStructTypeRefCount(*field->type());
- }
- return;
- }
-
- const auto *structure = type.getStruct();
- if (structure != nullptr)
- {
- auto structIter = mStructIdRefCounts.find(structure->uniqueId());
- if (structIter == mStructIdRefCounts.end())
- {
- mStructIdRefCounts[structure->uniqueId()] = 1u;
-
- for (const auto &field : structure->fields())
- {
- incrementStructTypeRefCount(*field->type());
- }
-
- return;
- }
- ++(structIter->second);
- }
-}
-
-void CollectVariableRefCountsTraverser::visitSymbol(TIntermSymbol *node)
-{
- incrementStructTypeRefCount(node->getType());
-
- auto iter = mSymbolIdRefCounts.find(node->getId());
- if (iter == mSymbolIdRefCounts.end())
- {
- mSymbolIdRefCounts[node->getId()] = 1u;
- return;
- }
- ++(iter->second);
-}
-
-bool CollectVariableRefCountsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- // This tracks struct references in both function calls and constructors.
- incrementStructTypeRefCount(node->getType());
- return true;
-}
-
-bool CollectVariableRefCountsTraverser::visitFunctionPrototype(Visit visit,
- TIntermFunctionPrototype *node)
-{
- incrementStructTypeRefCount(node->getType());
- return true;
-}
-
-// Traverser that removes all unreferenced variables on one traversal.
-class RemoveUnreferencedVariablesTraverser : public TIntermTraverser
-{
- public:
- RemoveUnreferencedVariablesTraverser(
- CollectVariableRefCountsTraverser::RefCountMap *symbolIdRefCounts,
- CollectVariableRefCountsTraverser::RefCountMap *structIdRefCounts,
- TSymbolTable *symbolTable);
-
- bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
- void visitSymbol(TIntermSymbol *node) override;
- bool visitAggregate(Visit visit, TIntermAggregate *node) override;
-
- // Traverse loop and block nodes in reverse order. Note that this traverser does not track
- // parent block positions, so insertStatementInParentBlock is unusable!
- void traverseBlock(TIntermBlock *block) override;
- void traverseLoop(TIntermLoop *loop) override;
-
- private:
- void removeVariableDeclaration(TIntermDeclaration *node, TIntermTyped *declarator);
- void decrementStructTypeRefCount(const TType &type);
-
- CollectVariableRefCountsTraverser::RefCountMap *mSymbolIdRefCounts;
- CollectVariableRefCountsTraverser::RefCountMap *mStructIdRefCounts;
- bool mRemoveReferences;
-};
-
-RemoveUnreferencedVariablesTraverser::RemoveUnreferencedVariablesTraverser(
- CollectVariableRefCountsTraverser::RefCountMap *symbolIdRefCounts,
- CollectVariableRefCountsTraverser::RefCountMap *structIdRefCounts,
- TSymbolTable *symbolTable)
- : TIntermTraverser(true, false, true, symbolTable),
- mSymbolIdRefCounts(symbolIdRefCounts),
- mStructIdRefCounts(structIdRefCounts),
- mRemoveReferences(false)
-{
-}
-
-void RemoveUnreferencedVariablesTraverser::decrementStructTypeRefCount(const TType &type)
-{
- auto *structure = type.getStruct();
- if (structure != nullptr)
- {
- ASSERT(mStructIdRefCounts->find(structure->uniqueId()) != mStructIdRefCounts->end());
- unsigned int structRefCount = --(*mStructIdRefCounts)[structure->uniqueId()];
-
- if (structRefCount == 0)
- {
- for (const auto &field : structure->fields())
- {
- decrementStructTypeRefCount(*field->type());
- }
- }
- }
-}
-
-void RemoveUnreferencedVariablesTraverser::removeVariableDeclaration(TIntermDeclaration *node,
- TIntermTyped *declarator)
-{
- if (declarator->getType().isStructSpecifier() && !declarator->getType().isNamelessStruct())
- {
- unsigned int structId = declarator->getType().getStruct()->uniqueId();
- if ((*mStructIdRefCounts)[structId] > 1u)
- {
- // 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
- // unreferenced variable.
-
- // Note that since we're not removing the entire declaration, the struct's reference
- // count will end up being one less than the correct refcount. But since the struct
- // declaration is kept, the incorrect refcount can't cause any other problems.
-
- if (declarator->getAsSymbolNode() && declarator->getAsSymbolNode()->getSymbol().empty())
- {
- // Already an empty declaration - nothing to do.
- return;
- }
- queueReplacementWithParent(node, declarator,
- new TIntermSymbol(mSymbolTable->getEmptySymbolId(),
- TString(""), declarator->getType()),
- OriginalNode::IS_DROPPED);
- return;
- }
- }
-
- if (getParentNode()->getAsBlock())
- {
- TIntermSequence emptyReplacement;
- mMultiReplacements.push_back(
- NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, emptyReplacement));
- }
- else
- {
- ASSERT(getParentNode()->getAsLoopNode());
- queueReplacement(nullptr, OriginalNode::IS_DROPPED);
- }
-}
-
-bool RemoveUnreferencedVariablesTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
-{
- if (visit == PreVisit)
- {
- // SeparateDeclarations should have already been run.
- ASSERT(node->getSequence()->size() == 1u);
-
- TIntermTyped *declarator = node->getSequence()->back()->getAsTyped();
- ASSERT(declarator);
-
- // We can only remove variables that are not a part of the shader interface.
- TQualifier qualifier = declarator->getQualifier();
- if (qualifier != EvqTemporary && qualifier != EvqGlobal)
- {
- return true;
- }
-
- bool canRemoveVariable = false;
- TIntermSymbol *symbolNode = declarator->getAsSymbolNode();
- if (symbolNode != nullptr)
- {
- canRemoveVariable =
- (*mSymbolIdRefCounts)[symbolNode->getId()] == 1u || symbolNode->getSymbol().empty();
- }
- TIntermBinary *initNode = declarator->getAsBinaryNode();
- if (initNode != nullptr)
- {
- ASSERT(initNode->getLeft()->getAsSymbolNode());
- int symbolId = initNode->getLeft()->getAsSymbolNode()->getId();
- canRemoveVariable =
- (*mSymbolIdRefCounts)[symbolId] == 1u && !initNode->getRight()->hasSideEffects();
- }
-
- if (canRemoveVariable)
- {
- removeVariableDeclaration(node, declarator);
- mRemoveReferences = true;
- }
- return true;
- }
- ASSERT(visit == PostVisit);
- mRemoveReferences = false;
- return true;
-}
-
-void RemoveUnreferencedVariablesTraverser::visitSymbol(TIntermSymbol *node)
-{
- if (mRemoveReferences)
- {
- ASSERT(mSymbolIdRefCounts->find(node->getId()) != mSymbolIdRefCounts->end());
- --(*mSymbolIdRefCounts)[node->getId()];
-
- decrementStructTypeRefCount(node->getType());
- }
-}
-
-bool RemoveUnreferencedVariablesTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- if (mRemoveReferences)
- {
- decrementStructTypeRefCount(node->getType());
- }
- return true;
-}
-
-void RemoveUnreferencedVariablesTraverser::traverseBlock(TIntermBlock *node)
-{
- // We traverse blocks in reverse order. This way reference counts can be decremented when
- // removing initializers, and variables that become unused when initializers are removed can be
- // removed on the same traversal.
-
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- TIntermSequence *sequence = node->getSequence();
-
- if (preVisit)
- visit = visitBlock(PreVisit, node);
-
- if (visit)
- {
- for (auto iter = sequence->rbegin(); iter != sequence->rend(); ++iter)
- {
- (*iter)->traverse(this);
- if (visit && inVisit)
- {
- if ((iter + 1) != sequence->rend())
- visit = visitBlock(InVisit, node);
- }
- }
- }
-
- if (visit && postVisit)
- visitBlock(PostVisit, node);
-}
-
-void RemoveUnreferencedVariablesTraverser::traverseLoop(TIntermLoop *node)
-{
- // We traverse loops in reverse order as well. The loop body gets traversed before the init
- // node.
-
- ScopedNodeInTraversalPath addToPath(this, node);
-
- bool visit = true;
-
- if (preVisit)
- visit = visitLoop(PreVisit, node);
-
- if (visit)
- {
- // We don't need to traverse loop expressions or conditions since they can't be declarations
- // in the AST (loops which have a declaration in their condition get transformed in the
- // parsing stage).
- ASSERT(node->getExpression() == nullptr ||
- node->getExpression()->getAsDeclarationNode() == nullptr);
- ASSERT(node->getCondition() == nullptr ||
- node->getCondition()->getAsDeclarationNode() == nullptr);
-
- if (node->getBody())
- node->getBody()->traverse(this);
-
- if (node->getInit())
- node->getInit()->traverse(this);
- }
-
- if (visit && postVisit)
- visitLoop(PostVisit, node);
-}
-
-} // namespace
-
-void RemoveUnreferencedVariables(TIntermBlock *root, TSymbolTable *symbolTable)
-{
- CollectVariableRefCountsTraverser collector;
- root->traverse(&collector);
- RemoveUnreferencedVariablesTraverser traverser(&collector.getSymbolIdRefCounts(),
- &collector.getStructIdRefCounts(), symbolTable);
- root->traverse(&traverser);
- traverser.updateTree();
-}
-
-} // namespace sh