Fix cases where SPIR-V conditionally branches to loop headers.

We should check if we are actually branching back to loop header.
Fixes some logic when continue_block == loop_header.
This commit is contained in:
Hans-Kristian Arntzen 2016-04-04 08:53:37 +02:00
parent 92134e410a
commit ba0ab875c8
3 changed files with 86 additions and 11 deletions

View File

@ -10,23 +10,61 @@ layout(binding = 0, std430) buffer SSBO
layout(binding = 1, std430) buffer SSBO2
{
vec4 out_data[];
} _125;
} _177;
void main()
{
uint ident = gl_GlobalInvocationID.x;
vec4 idat = _24.in_data[ident];
int k = 0;
uint i;
uint i = 0u;
uint i_1;
uint j;
int l;
if ((idat.y == 20.0))
{
do
{
k = (k * 2);
i = (i + uint(1));
} while ((i < ident));
}
switch (k)
{
case 10:
{
for (;;)
{
i = (i + uint(1));
if ((i > 10u))
{
break;
}
continue;
}
break;
}
default:
{
for (;;)
{
i = (i + 2u);
if ((i > 20u))
{
break;
}
continue;
}
break;
}
}
while ((k < 10))
{
idat = (idat * 2.0);
k = (k + 1);
}
i = 0u;
for (; (i < 16u); i = (i + uint(1)), k = (k + 1))
i_1 = 0u;
for (; (i_1 < 16u); i_1 = (i_1 + uint(1)), k = (k + 1))
{
j = 0u;
for (; (j < 30u); j = (j + uint(1)))
@ -67,6 +105,6 @@ void main()
l = (l + 1);
continue;
}
_125.out_data[ident] = idat;
_177.out_data[ident] = idat;
}

View File

@ -18,6 +18,38 @@ void main()
vec4 idat = in_data[ident];
int k = 0;
uint i = 0u;
if (idat.y == 20.0)
{
do
{
k = k * 2;
i++;
} while (i < ident);
}
switch (k)
{
case 10:
for (;;)
{
i++;
if (i > 10u)
break;
}
break;
default:
for (;;)
{
i += 2u;
if (i > 20u)
break;
}
break;
}
while (k < 10)
{
idat *= 2.0;

View File

@ -3701,7 +3701,9 @@ void CompilerGLSL::branch(uint32_t from, uint32_t to)
flush_phi(from, to);
flush_all_active_variables();
if (loop_block.find(to) != end(loop_block))
// This is only a continue if we branch to our loop dominator.
if (loop_block.find(to) != end(loop_block) &&
get<SPIRBlock>(from).loop_dominator == to)
{
// This can happen if we had a complex continue block which was emitted.
// Once the continue block tries to branch to the loop header, just emit continue;
@ -3813,20 +3815,23 @@ void CompilerGLSL::propagate_loop_dominators(const SPIRBlock &block)
block.loop_dominator = dominator;
};
// After merging a loop, we inherit the loop dominator always.
if (block.merge_block)
set_dominator(block.merge_block, block.loop_dominator);
if (block.true_block)
set_dominator(block.true_block, dominator);
if (block.false_block)
set_dominator(block.false_block, dominator);
if (block.next_block)
set_dominator(block.next_block, dominator);
if (block.continue_block)
set_dominator(block.continue_block, dominator);
for (auto &c : block.cases)
set_dominator(c.block, dominator);
// After merging a loop, we inherit the loop dominator always.
if (block.merge_block)
set_dominator(block.merge_block, block.loop_dominator);
// In older glslang output continue_block can be == loop header.
if (block.continue_block && block.continue_block != block.self)
set_dominator(block.continue_block, dominator);
}
}