Commit 4bd730c8 by Olli Etuaho Committed by Commit Bot

Recognize more non-fallthrough cases in switch/case

RemoveSwitchFallThrough now treats cases where break; or return; is nested inside a block as non-fallthrough to avoid unnecessary duplication of code. For example, the case 1 below would previously get treated as fall-through: switch(foo) { case 1: { break; } default: break; } Now RemoveSwitchFallThrough doesn't do anything to this code. BUG=chromium:772695 TEST=angle_end2end_tests Change-Id: Iafab6d8b05c63bcdb5f54834dbc1f41192c31dd4 Reviewed-on: https://chromium-review.googlesource.com/709197Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 6aee8620
...@@ -203,12 +203,29 @@ bool RemoveSwitchFallThroughTraverser::visitAggregate(Visit, TIntermAggregate *n ...@@ -203,12 +203,29 @@ bool RemoveSwitchFallThroughTraverser::visitAggregate(Visit, TIntermAggregate *n
return false; return false;
} }
bool DoesBlockAlwaysBreak(TIntermBlock *node)
{
if (node->getSequence()->empty())
{
return false;
}
TIntermBlock *lastStatementAsBlock = node->getSequence()->back()->getAsBlock();
if (lastStatementAsBlock)
{
return DoesBlockAlwaysBreak(lastStatementAsBlock);
}
TIntermBranch *lastStatementAsBranch = node->getSequence()->back()->getAsBranchNode();
return lastStatementAsBranch != nullptr;
}
bool RemoveSwitchFallThroughTraverser::visitBlock(Visit, TIntermBlock *node) bool RemoveSwitchFallThroughTraverser::visitBlock(Visit, TIntermBlock *node)
{ {
if (node != mStatementList) if (node != mStatementList)
{ {
mPreviousCase->getSequence()->push_back(node); mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false; mLastStatementWasBreak = DoesBlockAlwaysBreak(node);
return false; return false;
} }
return true; return true;
......
...@@ -3580,6 +3580,48 @@ TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration) ...@@ -3580,6 +3580,48 @@ TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader); ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
} }
// Test switch/case where break/return statements are within blocks.
TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
{
const std::string &fragmentShader =
R"(#version 300 es
precision highp float;
uniform int u_zero;
out vec4 my_FragColor;
bool test(int n)
{
switch(n) {
case 0:
{
{
break;
}
}
case 1:
{
return true;
}
case 2:
{
n++;
}
}
return false;
}
void main()
{
my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
drawQuad(program.get(), "inputAttribute", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(GLSLTest, ANGLE_INSTANTIATE_TEST(GLSLTest,
ES2_D3D9(), ES2_D3D9(),
......
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