Commit c457e7bb by Corentin Wallez

Revert "Implement discontinuous loops AST analysis"

This reverts commit f30a9ba9. Change-Id: I577cfd1e7d5d6138413c29205cbf4d35b6861226 Reviewed-on: https://chromium-review.googlesource.com/263754Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Tested-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 186160b2
...@@ -138,201 +138,6 @@ class PullGradient : public TIntermTraverser ...@@ -138,201 +138,6 @@ class PullGradient : public TIntermTraverser
std::vector<TIntermNode*> mParents; std::vector<TIntermNode*> mParents;
}; };
// Traverses the AST of a function definition, assuming it has already been used to
// traverse the callees of that function; computes the discontinuous loops and the if
// statements that contain a discontinuous loop in their call graph.
class PullComputeDiscontinuousLoops : public TIntermTraverser
{
public:
PullComputeDiscontinuousLoops(MetadataList *metadataList, size_t index, const CallDAG &dag)
: TIntermTraverser(true, false, true),
mMetadataList(metadataList),
mMetadata(&(*metadataList)[index]),
mIndex(index),
mDag(dag)
{
}
void traverse(TIntermAggregate *node)
{
node->traverse(this);
ASSERT(mLoops.empty());
ASSERT(mIfs.empty());
}
// Called when a discontinuous loop or a call to a function with a discontinuous loop
// in its call graph is found.
void onDiscontinuousLoop()
{
mMetadata->mHasDiscontinuousLoopInCallGraph = true;
// Mark the latest if as using a discontinuous loop.
if (!mIfs.empty())
{
mMetadata->mIfsContainingDiscontinuousLoop.insert(mIfs.back());
}
}
bool visitLoop(Visit visit, TIntermLoop *loop)
{
if (visit == PreVisit)
{
mLoops.push_back(loop);
}
else if (visit == PostVisit)
{
ASSERT(mLoops.back() == loop);
mLoops.pop_back();
}
return true;
}
bool visitSelection(Visit visit, TIntermSelection *node)
{
if (visit == PreVisit)
{
mIfs.push_back(node);
}
else if (visit == PostVisit)
{
ASSERT(mIfs.back() == node);
mIfs.pop_back();
// An if using a discontinuous loop means its parents ifs are also discontinuous.
if (mMetadata->mIfsContainingDiscontinuousLoop.count(node) > 0 && !mIfs.empty())
{
mMetadata->mIfsContainingDiscontinuousLoop.insert(mIfs.back());
}
}
return true;
}
bool visitBranch(Visit visit, TIntermBranch *node)
{
if (visit == PreVisit)
{
switch (node->getFlowOp())
{
case EOpKill:
break;
case EOpBreak:
case EOpContinue:
ASSERT(!mLoops.empty());
mMetadata->mDiscontinuousLoops.insert(mLoops.back());
onDiscontinuousLoop();
break;
case EOpReturn:
// A return jumps out of all the enclosing loops
if (!mLoops.empty())
{
for (TIntermLoop* loop : mLoops)
{
mMetadata->mDiscontinuousLoops.insert(loop);
}
onDiscontinuousLoop();
}
break;
default:
UNREACHABLE();
}
}
return true;
}
bool visitAggregate(Visit visit, TIntermAggregate *node) override
{
if (visit == PreVisit && node->getOp() == EOpFunctionCall)
{
if (node->isUserDefined())
{
size_t calleeIndex = mDag.findIndex(node);
ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
if ((*mMetadataList)[calleeIndex].mHasDiscontinuousLoopInCallGraph)
{
onDiscontinuousLoop();
}
}
}
return true;
}
private:
MetadataList *mMetadataList;
ASTMetadataHLSL *mMetadata;
size_t mIndex;
const CallDAG &mDag;
std::vector<TIntermLoop*> mLoops;
std::vector<TIntermSelection*> mIfs;
};
// Tags all the functions called in a discontinuous loop
class PushDiscontinuousLoops : public TIntermTraverser
{
public:
PushDiscontinuousLoops(MetadataList *metadataList, size_t index, const CallDAG &dag)
: TIntermTraverser(true, true, true),
mMetadataList(metadataList),
mMetadata(&(*metadataList)[index]),
mIndex(index),
mDag(dag),
mNestedDiscont(mMetadata->mCalledInDiscontinuousLoop ? 1 : 0)
{
}
void traverse(TIntermAggregate *node)
{
node->traverse(this);
ASSERT(mNestedDiscont == (mMetadata->mCalledInDiscontinuousLoop ? 1 : 0));
}
bool visitLoop(Visit visit, TIntermLoop *loop)
{
bool isDiscontinuous = mMetadata->mDiscontinuousLoops.count(loop) > 0;
if (visit == PreVisit && isDiscontinuous)
{
mNestedDiscont++;
}
else if (visit == PostVisit && isDiscontinuous)
{
mNestedDiscont--;
}
return true;
}
bool visitAggregate(Visit visit, TIntermAggregate *node) override
{
switch (node->getOp())
{
case EOpFunctionCall:
if (visit == PreVisit && node->isUserDefined() && mNestedDiscont > 0)
{
size_t calleeIndex = mDag.findIndex(node);
ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
(*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true;
}
break;
default:
break;
}
return true;
}
private:
MetadataList *mMetadataList;
ASTMetadataHLSL *mMetadata;
size_t mIndex;
const CallDAG &mDag;
int mNestedDiscont;
};
} }
bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermSelection *node) bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermSelection *node)
...@@ -345,11 +150,6 @@ bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node) ...@@ -345,11 +150,6 @@ bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node)
return mControlFlowsContainingGradient.count(node) > 0; return mControlFlowsContainingGradient.count(node) > 0;
} }
bool ASTMetadataHLSL::hasDiscontinuousLoop(TIntermSelection *node)
{
return mIfsContainingDiscontinuousLoop.count(node) > 0;
}
MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag) MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag)
{ {
MetadataList metadataList(callDag.size()); MetadataList metadataList(callDag.size());
...@@ -377,35 +177,5 @@ MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag) ...@@ -377,35 +177,5 @@ MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag)
pull.traverse(callDag.getRecordFromIndex(i).node); pull.traverse(callDag.getRecordFromIndex(i).node);
} }
// Compute which loops are discontinuous and which function are called in
// these loops. The same way computing gradient usage is a "pull" process,
// computing "bing used in a discont. loop" is a push process. However we also
// need to know what ifs have a discontinuous loop inside so we do the same type
// of callgraph analysis as for the gradient.
// First compute which loops are discontinuous (no specific order) and pull
// the ifs and functions using a discontinuous loop.
for (size_t i = 0; i < callDag.size(); i++)
{
PullComputeDiscontinuousLoops pull(&metadataList, i, callDag);
pull.traverse(callDag.getRecordFromIndex(i).node);
}
// Then push the information to callees, either from the a local discontinuous
// loop or from the caller being called in a discontinuous loop already
for (size_t i = callDag.size(); i-- > 0;)
{
PushDiscontinuousLoops push(&metadataList, i, callDag);
push.traverse(callDag.getRecordFromIndex(i).node);
}
// We create "Lod0" version of functions with the gradient operations replaced
// by non-gradient operations so that the D3D compiler is happier with discont
// loops.
for (auto &metadata : metadataList)
{
metadata.mNeedsLod0 = metadata.mCalledInDiscontinuousLoop && metadata.mUsesGradient;
}
return metadataList; return metadataList;
} }
\ No newline at end of file
...@@ -20,10 +20,7 @@ class TIntermLoop; ...@@ -20,10 +20,7 @@ class TIntermLoop;
struct ASTMetadataHLSL struct ASTMetadataHLSL
{ {
ASTMetadataHLSL() ASTMetadataHLSL()
: mUsesGradient(false), : mUsesGradient(false)
mCalledInDiscontinuousLoop(false),
mHasDiscontinuousLoopInCallGraph(false),
mNeedsLod0(false)
{ {
} }
...@@ -31,7 +28,6 @@ struct ASTMetadataHLSL ...@@ -31,7 +28,6 @@ struct ASTMetadataHLSL
// gradient operation, or a call to a function that uses a gradient. // gradient operation, or a call to a function that uses a gradient.
bool hasGradientInCallGraph(TIntermSelection *node); bool hasGradientInCallGraph(TIntermSelection *node);
bool hasGradientInCallGraph(TIntermLoop *node); bool hasGradientInCallGraph(TIntermLoop *node);
bool hasDiscontinuousLoop(TIntermSelection *node);
// Does the function use a gradient. // Does the function use a gradient.
bool mUsesGradient; bool mUsesGradient;
...@@ -39,16 +35,6 @@ struct ASTMetadataHLSL ...@@ -39,16 +35,6 @@ struct ASTMetadataHLSL
// Even if usesGradient is true, some control flow might not use a gradient // Even if usesGradient is true, some control flow might not use a gradient
// so we store the set of all gradient-using control flows. // so we store the set of all gradient-using control flows.
std::set<TIntermNode*> mControlFlowsContainingGradient; std::set<TIntermNode*> mControlFlowsContainingGradient;
// Remember information about the discontinuous loops and which functions
// are called in such loops.
bool mCalledInDiscontinuousLoop;
bool mHasDiscontinuousLoopInCallGraph;
std::set<TIntermLoop*> mDiscontinuousLoops;
std::set<TIntermSelection*> mIfsContainingDiscontinuousLoop;
// Will we need to generate a Lod0 version of the function.
bool mNeedsLod0;
}; };
typedef std::vector<ASTMetadataHLSL> MetadataList; typedef std::vector<ASTMetadataHLSL> MetadataList;
......
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