Deal with nested loops.

Actually need to hoist out variable to outermost loop.
This commit is contained in:
Hans-Kristian Arntzen 2019-06-06 14:37:02 +02:00
parent 02ae99f399
commit 6b52b0fe8b
3 changed files with 33 additions and 23 deletions

View File

@ -8,19 +8,22 @@ void main()
{
bool written = false;
float v;
for (mediump int i = 0; i < 4; i++)
for (mediump int j = 0; j < 10; j++)
{
float w = 0.0;
if (written)
for (mediump int i = 0; i < 4; i++)
{
w += v;
float w = 0.0;
if (written)
{
w += v;
}
else
{
v = 20.0;
}
v += float(i);
written = true;
}
else
{
v = 20.0;
}
v += float(i);
written = true;
}
FragColor = vec4(1.0);
}

View File

@ -6,16 +6,19 @@ void main()
{
float v;
bool written = false;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 10; j++)
{
float w = 0.0;
if (written)
w += v;
else
v = 20.0;
for (int i = 0; i < 4; i++)
{
float w = 0.0;
if (written)
w += v;
else
v = 20.0;
v += float(i);
written = true;
v += float(i);
written = true;
}
}
FragColor = vec4(1.0);
}

View File

@ -3354,20 +3354,24 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry, AnalyzeVariableScopeA
// actually need to be preserved across loop iterations. We can express this by adding
// a "read" access to the loop header.
// In the dominating block, we must see an OpStore or equivalent as the first access of an OpVariable.
// Should that fail, we look for the innermost loop header and tack on an access there.
// Should that fail, we look for the outermost loop header and tack on an access there.
// Phi nodes cannot have this problem.
if (dominating_block)
{
auto &variable = get<SPIRVariable>(var.first);
if (!variable.phi_variable)
{
auto &block = get<SPIRBlock>(dominating_block);
bool preserve = may_read_undefined_variable_in_block(block, var.first);
auto *block = &get<SPIRBlock>(dominating_block);
bool preserve = may_read_undefined_variable_in_block(*block, var.first);
if (preserve)
{
if (block.loop_dominator != SPIRBlock::NoDominator)
// Find the outermost loop scope.
while (block->loop_dominator != SPIRBlock::NoDominator)
block = &get<SPIRBlock>(block->loop_dominator);
if (block->self != dominating_block)
{
builder.add_block(block.loop_dominator);
builder.add_block(block->self);
dominating_block = builder.get_dominator();
}
}