Commit c9c259cc by Olli Etuaho Committed by Commit Bot

Add a shared traverse() function for most node types

The traversal logic for many node types is essentially the same. Use a single traverse() function for all simple node types instead of having different ones for each node type. Special traversal code is only needed for those node types where the traversal logic is overridden in specific traversers or which do special bookkeeping. This makes traverser behavior a bit more consistent: InVisit calls are now done for all node types, including if/else, ternary and loop nodes. Also false returned from visit function will always skip traversing the next children of that node. This reduces shader_translator binary size on Windows by 8 kilobytes. The added helper functions will also make it easier to implement alternative more efficient traversers. Unfortunately this also regresses compiler perf tests by around 2-3%. BUG=angleproject:2662 TEST=angle_unittests, angle_end2end_tests Change-Id: I3cb1256297b66e1db4b133b8fb84a24c349a9e29 Reviewed-on: https://chromium-review.googlesource.com/1133009Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 5598148b
...@@ -197,6 +197,7 @@ ...@@ -197,6 +197,7 @@
'compiler/translator/tree_util/ReplaceVariable.h', 'compiler/translator/tree_util/ReplaceVariable.h',
'compiler/translator/tree_util/RunAtTheEndOfShader.cpp', 'compiler/translator/tree_util/RunAtTheEndOfShader.cpp',
'compiler/translator/tree_util/RunAtTheEndOfShader.h', 'compiler/translator/tree_util/RunAtTheEndOfShader.h',
'compiler/translator/tree_util/Visit.h',
'third_party/compiler/ArrayBoundsClamper.cpp', 'third_party/compiler/ArrayBoundsClamper.cpp',
'third_party/compiler/ArrayBoundsClamper.h', 'third_party/compiler/ArrayBoundsClamper.h',
], ],
......
...@@ -202,6 +202,61 @@ void TIntermExpression::setTypePreservePrecision(const TType &t) ...@@ -202,6 +202,61 @@ void TIntermExpression::setTypePreservePrecision(const TType &t)
return true; \ return true; \
} }
unsigned int TIntermSymbol::getChildCount()
{
return 0;
}
TIntermNode *TIntermSymbol::getChildNode(unsigned int index)
{
UNREACHABLE();
return nullptr;
}
unsigned int TIntermConstantUnion::getChildCount()
{
return 0;
}
TIntermNode *TIntermConstantUnion::getChildNode(unsigned int index)
{
UNREACHABLE();
return nullptr;
}
unsigned int TIntermLoop::getChildCount()
{
return (mInit ? 1 : 0) + (mCond ? 1 : 0) + (mExpr ? 1 : 0) + (mBody ? 1 : 0);
}
TIntermNode *TIntermLoop::getChildNode(unsigned int index)
{
TIntermNode *children[4];
unsigned int childIndex = 0;
if (mInit)
{
children[childIndex] = mInit;
++childIndex;
}
if (mCond)
{
children[childIndex] = mCond;
++childIndex;
}
if (mExpr)
{
children[childIndex] = mExpr;
++childIndex;
}
if (mBody)
{
children[childIndex] = mBody;
++childIndex;
}
ASSERT(index < childIndex);
return children[index];
}
bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
ASSERT(original != nullptr); // This risks replacing multiple children. ASSERT(original != nullptr); // This risks replacing multiple children.
...@@ -212,12 +267,36 @@ bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replaceme ...@@ -212,12 +267,36 @@ bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replaceme
return false; return false;
} }
unsigned int TIntermBranch::getChildCount()
{
return (mExpression ? 1 : 0);
}
TIntermNode *TIntermBranch::getChildNode(unsigned int index)
{
ASSERT(mExpression);
ASSERT(index == 0);
return mExpression;
}
bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
return false; return false;
} }
unsigned int TIntermSwizzle::getChildCount()
{
return 1;
}
TIntermNode *TIntermSwizzle::getChildNode(unsigned int index)
{
ASSERT(mOperand);
ASSERT(index == 0);
return mOperand;
}
bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
...@@ -225,6 +304,21 @@ bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replac ...@@ -225,6 +304,21 @@ bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replac
return false; return false;
} }
unsigned int TIntermBinary::getChildCount()
{
return 2;
}
TIntermNode *TIntermBinary::getChildNode(unsigned int index)
{
ASSERT(index < 2);
if (index == 0)
{
return mLeft;
}
return mRight;
}
bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
...@@ -232,6 +326,18 @@ bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replace ...@@ -232,6 +326,18 @@ bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replace
return false; return false;
} }
unsigned int TIntermUnary::getChildCount()
{
return 1;
}
TIntermNode *TIntermUnary::getChildNode(unsigned int index)
{
ASSERT(mOperand);
ASSERT(index == 0);
return mOperand;
}
bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
...@@ -239,12 +345,39 @@ bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacem ...@@ -239,12 +345,39 @@ bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacem
return false; return false;
} }
unsigned int TIntermInvariantDeclaration::getChildCount()
{
return 1;
}
TIntermNode *TIntermInvariantDeclaration::getChildNode(unsigned int index)
{
ASSERT(mSymbol);
ASSERT(index == 0);
return mSymbol;
}
bool TIntermInvariantDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermInvariantDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
REPLACE_IF_IS(mSymbol, TIntermSymbol, original, replacement); REPLACE_IF_IS(mSymbol, TIntermSymbol, original, replacement);
return false; return false;
} }
unsigned int TIntermFunctionDefinition::getChildCount()
{
return 2;
}
TIntermNode *TIntermFunctionDefinition::getChildNode(unsigned int index)
{
ASSERT(index < 2);
if (index == 0)
{
return mPrototype;
}
return mBody;
}
bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
REPLACE_IF_IS(mPrototype, TIntermFunctionPrototype, original, replacement); REPLACE_IF_IS(mPrototype, TIntermFunctionPrototype, original, replacement);
...@@ -252,21 +385,62 @@ bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermN ...@@ -252,21 +385,62 @@ bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermN
return false; return false;
} }
unsigned int TIntermAggregate::getChildCount()
{
return mArguments.size();
}
TIntermNode *TIntermAggregate::getChildNode(unsigned int index)
{
return mArguments[index];
}
bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
return replaceChildNodeInternal(original, replacement); return replaceChildNodeInternal(original, replacement);
} }
unsigned int TIntermBlock::getChildCount()
{
return mStatements.size();
}
TIntermNode *TIntermBlock::getChildNode(unsigned int index)
{
return mStatements[index];
}
bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
return replaceChildNodeInternal(original, replacement); return replaceChildNodeInternal(original, replacement);
} }
unsigned int TIntermFunctionPrototype::getChildCount()
{
return 0;
}
TIntermNode *TIntermFunctionPrototype::getChildNode(unsigned int index)
{
UNREACHABLE();
return nullptr;
}
bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
return false; return false;
} }
unsigned int TIntermDeclaration::getChildCount()
{
return mDeclarators.size();
}
TIntermNode *TIntermDeclaration::getChildNode(unsigned int index)
{
return mDeclarators[index];
}
bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
return replaceChildNodeInternal(original, replacement); return replaceChildNodeInternal(original, replacement);
...@@ -700,6 +874,25 @@ void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator) ...@@ -700,6 +874,25 @@ void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
mDeclarators.push_back(declarator); mDeclarators.push_back(declarator);
} }
unsigned int TIntermTernary::getChildCount()
{
return 3;
}
TIntermNode *TIntermTernary::getChildNode(unsigned int index)
{
ASSERT(index < 3);
if (index == 0)
{
return mCondition;
}
if (index == 1)
{
return mTrueExpression;
}
return mFalseExpression;
}
bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
...@@ -708,6 +901,24 @@ bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replac ...@@ -708,6 +901,24 @@ bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replac
return false; return false;
} }
unsigned int TIntermIfElse::getChildCount()
{
return 1 + (mTrueBlock ? 1 : 0) + (mFalseBlock ? 1 : 0);
}
TIntermNode *TIntermIfElse::getChildNode(unsigned int index)
{
if (index == 0)
{
return mCondition;
}
if (mTrueBlock && index == 1)
{
return mTrueBlock;
}
return mFalseBlock;
}
bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
...@@ -716,6 +927,21 @@ bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replace ...@@ -716,6 +927,21 @@ bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replace
return false; return false;
} }
unsigned int TIntermSwitch::getChildCount()
{
return 2;
}
TIntermNode *TIntermSwitch::getChildNode(unsigned int index)
{
ASSERT(index < 2);
if (index == 0)
{
return mInit;
}
return mStatementList;
}
bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
REPLACE_IF_IS(mInit, TIntermTyped, original, replacement); REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
...@@ -724,6 +950,18 @@ bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replace ...@@ -724,6 +950,18 @@ bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replace
return false; return false;
} }
unsigned int TIntermCase::getChildCount()
{
return (mCondition ? 1 : 0);
}
TIntermNode *TIntermCase::getChildNode(unsigned int index)
{
ASSERT(index == 0);
ASSERT(mCondition);
return mCondition;
}
bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
...@@ -1117,6 +1355,7 @@ TIntermLoop::TIntermLoop(TLoopType type, ...@@ -1117,6 +1355,7 @@ TIntermLoop::TIntermLoop(TLoopType type,
TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB) TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB)
: TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB) : TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB)
{ {
ASSERT(mCondition);
// Prune empty false blocks so that there won't be unnecessary operations done on it. // Prune empty false blocks so that there won't be unnecessary operations done on it.
if (mFalseBlock && mFalseBlock->getSequence()->empty()) if (mFalseBlock && mFalseBlock->getSequence()->empty())
{ {
...@@ -1127,6 +1366,7 @@ TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlo ...@@ -1127,6 +1366,7 @@ TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlo
TIntermSwitch::TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList) TIntermSwitch::TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList)
: TIntermNode(), mInit(init), mStatementList(statementList) : TIntermNode(), mInit(init), mStatementList(statementList)
{ {
ASSERT(mInit);
ASSERT(mStatementList); ASSERT(mStatementList);
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define COMPILER_TRANSLATOR_TREEUTIL_INTERMTRAVERSE_H_ #define COMPILER_TRANSLATOR_TREEUTIL_INTERMTRAVERSE_H_
#include "compiler/translator/IntermNode.h" #include "compiler/translator/IntermNode.h"
#include "compiler/translator/tree_util/Visit.h"
namespace sh namespace sh
{ {
...@@ -17,13 +18,6 @@ namespace sh ...@@ -17,13 +18,6 @@ namespace sh
class TSymbolTable; class TSymbolTable;
class TSymbolUniqueId; class TSymbolUniqueId;
enum Visit
{
PreVisit,
InVisit,
PostVisit
};
// For traversing the tree. User should derive from this class overriding the visit functions, // For traversing the tree. User should derive from this class overriding the visit functions,
// and then pass an object of the subclass to a traverse method of a node. // and then pass an object of the subclass to a traverse method of a node.
// //
...@@ -73,23 +67,21 @@ class TIntermTraverser : angle::NonCopyable ...@@ -73,23 +67,21 @@ class TIntermTraverser : angle::NonCopyable
// The traverse functions contain logic for iterating over the children of the node // The traverse functions contain logic for iterating over the children of the node
// and calling the visit functions in the appropriate places. They also track some // and calling the visit functions in the appropriate places. They also track some
// context that may be used by the visit functions. // context that may be used by the visit functions.
virtual void traverseSymbol(TIntermSymbol *node);
virtual void traverseConstantUnion(TIntermConstantUnion *node); // The generic traverse() function is used for nodes that don't need special handling.
virtual void traverseSwizzle(TIntermSwizzle *node); // It's templated in order to avoid virtual function calls, this gains around 2% compiler
// performance.
template <typename T>
void traverse(T *node);
// Specialized traverse functions are implemented for node types where traversal logic may need
// to be overridden or where some special bookkeeping needs to be done.
virtual void traverseBinary(TIntermBinary *node); virtual void traverseBinary(TIntermBinary *node);
virtual void traverseUnary(TIntermUnary *node); virtual void traverseUnary(TIntermUnary *node);
virtual void traverseTernary(TIntermTernary *node);
virtual void traverseIfElse(TIntermIfElse *node);
virtual void traverseSwitch(TIntermSwitch *node);
virtual void traverseCase(TIntermCase *node);
virtual void traverseFunctionPrototype(TIntermFunctionPrototype *node);
virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node); virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node);
virtual void traverseAggregate(TIntermAggregate *node); virtual void traverseAggregate(TIntermAggregate *node);
virtual void traverseBlock(TIntermBlock *node); virtual void traverseBlock(TIntermBlock *node);
virtual void traverseInvariantDeclaration(TIntermInvariantDeclaration *node);
virtual void traverseDeclaration(TIntermDeclaration *node);
virtual void traverseLoop(TIntermLoop *node); virtual void traverseLoop(TIntermLoop *node);
virtual void traverseBranch(TIntermBranch *node);
int getMaxDepth() const { return mMaxDepth; } int getMaxDepth() const { return mMaxDepth; }
...@@ -134,6 +126,10 @@ class TIntermTraverser : angle::NonCopyable ...@@ -134,6 +126,10 @@ class TIntermTraverser : angle::NonCopyable
TIntermTraverser *mTraverser; TIntermTraverser *mTraverser;
bool mWithinDepthLimit; bool mWithinDepthLimit;
}; };
// Optimized traversal functions for leaf nodes directly access ScopedNodeInTraversalPath.
friend void TIntermSymbol::traverse(TIntermTraverser *);
friend void TIntermConstantUnion::traverse(TIntermTraverser *);
friend void TIntermFunctionPrototype::traverse(TIntermTraverser *);
TIntermNode *getParentNode() { return mPath.size() <= 1 ? nullptr : mPath[mPath.size() - 2u]; } TIntermNode *getParentNode() { return mPath.size() <= 1 ? nullptr : mPath[mPath.size() - 2u]; }
......
//
// Copyright (c) 2018 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.
//
#ifndef COMPILER_TRANSLATOR_TREEUTIL_VISIT_H_
#define COMPILER_TRANSLATOR_TREEUTIL_VISIT_H_
namespace sh
{
enum Visit
{
PreVisit,
InVisit,
PostVisit
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_TREEUTIL_VISIT_H_
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