Commit 3873cd0b by Olli Etuaho

Fix issues with computing discontinuous loops

AST analysis to narrow down usage of [[loop]] and [[unroll]] failed to account for break statements inside switch statements. Add switch statement handling. This fixes asserts/crashes in dEQP tests. BUG=angleproject:937 TEST=dEQP-GLES3.functional.shaders.switch.* Change-Id: I04fdfe4733772a2a234934123bbfacf0376df562 Reviewed-on: https://chromium-review.googlesource.com/265191Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 5f2feee4
...@@ -156,7 +156,7 @@ class PullComputeDiscontinuousLoops : public TIntermTraverser ...@@ -156,7 +156,7 @@ class PullComputeDiscontinuousLoops : public TIntermTraverser
void traverse(TIntermAggregate *node) void traverse(TIntermAggregate *node)
{ {
node->traverse(this); node->traverse(this);
ASSERT(mLoops.empty()); ASSERT(mLoopsAndSwitches.empty());
ASSERT(mIfs.empty()); ASSERT(mIfs.empty());
} }
...@@ -172,22 +172,22 @@ class PullComputeDiscontinuousLoops : public TIntermTraverser ...@@ -172,22 +172,22 @@ class PullComputeDiscontinuousLoops : public TIntermTraverser
} }
} }
bool visitLoop(Visit visit, TIntermLoop *loop) bool visitLoop(Visit visit, TIntermLoop *loop) override
{ {
if (visit == PreVisit) if (visit == PreVisit)
{ {
mLoops.push_back(loop); mLoopsAndSwitches.push_back(loop);
} }
else if (visit == PostVisit) else if (visit == PostVisit)
{ {
ASSERT(mLoops.back() == loop); ASSERT(mLoopsAndSwitches.back() == loop);
mLoops.pop_back(); mLoopsAndSwitches.pop_back();
} }
return true; return true;
} }
bool visitSelection(Visit visit, TIntermSelection *node) bool visitSelection(Visit visit, TIntermSelection *node) override
{ {
if (visit == PreVisit) if (visit == PreVisit)
{ {
...@@ -207,7 +207,7 @@ class PullComputeDiscontinuousLoops : public TIntermTraverser ...@@ -207,7 +207,7 @@ class PullComputeDiscontinuousLoops : public TIntermTraverser
return true; return true;
} }
bool visitBranch(Visit visit, TIntermBranch *node) bool visitBranch(Visit visit, TIntermBranch *node) override
{ {
if (visit == PreVisit) if (visit == PreVisit)
{ {
...@@ -216,18 +216,42 @@ class PullComputeDiscontinuousLoops : public TIntermTraverser ...@@ -216,18 +216,42 @@ class PullComputeDiscontinuousLoops : public TIntermTraverser
case EOpKill: case EOpKill:
break; break;
case EOpBreak: case EOpBreak:
{
ASSERT(!mLoopsAndSwitches.empty());
TIntermLoop *loop = mLoopsAndSwitches.back()->getAsLoopNode();
if (loop != nullptr)
{
mMetadata->mDiscontinuousLoops.insert(loop);
onDiscontinuousLoop();
}
}
break;
case EOpContinue: case EOpContinue:
ASSERT(!mLoops.empty()); {
mMetadata->mDiscontinuousLoops.insert(mLoops.back()); ASSERT(!mLoopsAndSwitches.empty());
onDiscontinuousLoop(); TIntermLoop *loop = nullptr;
size_t i = mLoopsAndSwitches.size();
while (loop == nullptr && i > 0)
{
--i;
loop = mLoopsAndSwitches.at(i)->getAsLoopNode();
}
ASSERT(loop != nullptr);
mMetadata->mDiscontinuousLoops.insert(loop);
onDiscontinuousLoop();
}
break; break;
case EOpReturn: case EOpReturn:
// A return jumps out of all the enclosing loops // A return jumps out of all the enclosing loops
if (!mLoops.empty()) if (!mLoopsAndSwitches.empty())
{ {
for (TIntermLoop* loop : mLoops) for (TIntermNode* node : mLoopsAndSwitches)
{ {
mMetadata->mDiscontinuousLoops.insert(loop); TIntermLoop *loop = node->getAsLoopNode();
if (loop)
{
mMetadata->mDiscontinuousLoops.insert(loop);
}
} }
onDiscontinuousLoop(); onDiscontinuousLoop();
} }
...@@ -259,13 +283,27 @@ class PullComputeDiscontinuousLoops : public TIntermTraverser ...@@ -259,13 +283,27 @@ class PullComputeDiscontinuousLoops : public TIntermTraverser
return true; return true;
} }
bool visitSwitch(Visit visit, TIntermSwitch *node) override
{
if (visit == PreVisit)
{
mLoopsAndSwitches.push_back(node);
}
else if (visit == PostVisit)
{
ASSERT(mLoopsAndSwitches.back() == node);
mLoopsAndSwitches.pop_back();
}
return true;
}
private: private:
MetadataList *mMetadataList; MetadataList *mMetadataList;
ASTMetadataHLSL *mMetadata; ASTMetadataHLSL *mMetadata;
size_t mIndex; size_t mIndex;
const CallDAG &mDag; const CallDAG &mDag;
std::vector<TIntermLoop*> mLoops; std::vector<TIntermNode*> mLoopsAndSwitches;
std::vector<TIntermSelection*> mIfs; std::vector<TIntermSelection*> mIfs;
}; };
......
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