Elide branches to continue block when continue block is also a merge.
This commit is contained in:
parent
903ef0e40a
commit
55c2ca90ae
@ -11,12 +11,10 @@ void main()
|
|||||||
if (v0.x == 20.0)
|
if (v0.x == 20.0)
|
||||||
{
|
{
|
||||||
FragColor += vec4(v0[_54 & 3]);
|
FragColor += vec4(v0[_54 & 3]);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FragColor += vec4(v0[_54 & 1]);
|
FragColor += vec4(v0[_54 & 1]);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,10 @@ void main()
|
|||||||
if ((vA + _57) == 20)
|
if ((vA + _57) == 20)
|
||||||
{
|
{
|
||||||
_58 = 50;
|
_58 = 50;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_58 = ((vB + _57) == 40) ? 60 : _60;
|
_58 = ((vB + _57) == 40) ? 60 : _60;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,10 @@ void main()
|
|||||||
if (v0.x == 20.0)
|
if (v0.x == 20.0)
|
||||||
{
|
{
|
||||||
FragColor += vec4(v0[i & 3]);
|
FragColor += vec4(v0[i & 3]);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FragColor += vec4(v0[i & 1]);
|
FragColor += vec4(v0[i & 1]);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11285,7 +11285,7 @@ void CompilerGLSL::branch_to_continue(uint32_t from, uint32_t to)
|
|||||||
|
|
||||||
// Some simplification for for-loops. We always end up with a useless continue;
|
// Some simplification for for-loops. We always end up with a useless continue;
|
||||||
// statement since we branch to a loop block.
|
// statement since we branch to a loop block.
|
||||||
// Walk the CFG, if we uncoditionally execute the block calling continue assuming we're in the loop block,
|
// Walk the CFG, if we unconditionally execute the block calling continue assuming we're in the loop block,
|
||||||
// we can avoid writing out an explicit continue statement.
|
// we can avoid writing out an explicit continue statement.
|
||||||
// Similar optimization to return statements if we know we're outside flow control.
|
// Similar optimization to return statements if we know we're outside flow control.
|
||||||
if (!outside_control_flow)
|
if (!outside_control_flow)
|
||||||
@ -11298,6 +11298,8 @@ void CompilerGLSL::branch(uint32_t from, uint32_t to)
|
|||||||
flush_phi(from, to);
|
flush_phi(from, to);
|
||||||
flush_control_dependent_expressions(from);
|
flush_control_dependent_expressions(from);
|
||||||
|
|
||||||
|
bool to_is_continue = is_continue(to);
|
||||||
|
|
||||||
// This is only a continue if we branch to our loop dominator.
|
// This is only a continue if we branch to our loop dominator.
|
||||||
if ((ir.block_meta[to] & ParsedIR::BLOCK_META_LOOP_HEADER_BIT) != 0 && get<SPIRBlock>(from).loop_dominator == to)
|
if ((ir.block_meta[to] & ParsedIR::BLOCK_META_LOOP_HEADER_BIT) != 0 && get<SPIRBlock>(from).loop_dominator == to)
|
||||||
{
|
{
|
||||||
@ -11326,12 +11328,25 @@ void CompilerGLSL::branch(uint32_t from, uint32_t to)
|
|||||||
}
|
}
|
||||||
statement("break;");
|
statement("break;");
|
||||||
}
|
}
|
||||||
else if (is_continue(to) || (from == to))
|
else if (to_is_continue || from == to)
|
||||||
{
|
{
|
||||||
// For from == to case can happen for a do-while loop which branches into itself.
|
// For from == to case can happen for a do-while loop which branches into itself.
|
||||||
// We don't mark these cases as continue blocks, but the only possible way to branch into
|
// We don't mark these cases as continue blocks, but the only possible way to branch into
|
||||||
// ourselves is through means of continue blocks.
|
// ourselves is through means of continue blocks.
|
||||||
branch_to_continue(from, to);
|
|
||||||
|
// If we are merging to a continue block, there is no need to emit the block chain for continue here.
|
||||||
|
// We can branch to the continue block after we merge execution.
|
||||||
|
|
||||||
|
// Here we make use of structured control flow rules from spec:
|
||||||
|
// 2.11: - the merge block declared by a header block cannot be a merge block declared by any other header block
|
||||||
|
// - each header block must strictly dominate its merge block, unless the merge block is unreachable in the CFG
|
||||||
|
// If we are branching to a merge block, we must be inside a construct which dominates the merge block.
|
||||||
|
auto &block_meta = ir.block_meta[to];
|
||||||
|
bool branching_to_merge =
|
||||||
|
(block_meta & (ParsedIR::BLOCK_META_SELECTION_MERGE_BIT | ParsedIR::BLOCK_META_MULTISELECT_MERGE_BIT |
|
||||||
|
ParsedIR::BLOCK_META_LOOP_MERGE_BIT)) != 0;
|
||||||
|
if (!to_is_continue || !branching_to_merge)
|
||||||
|
branch_to_continue(from, to);
|
||||||
}
|
}
|
||||||
else if (!is_conditional(to))
|
else if (!is_conditional(to))
|
||||||
emit_block_chain(get<SPIRBlock>(to));
|
emit_block_chain(get<SPIRBlock>(to));
|
||||||
|
Loading…
Reference in New Issue
Block a user