Commit 75b6f212 by Ben Clayton

SpirvShader: Fix another edge case with phis and loops

If the merge block M contains phis, and M is a loop header of a second loop, we will get assertions that the back edges of the second loop have not yet been generated. We're only trying to update the phis of M for the lane exits of the first loop, so filter the phi updates to edges from those blocks. Bug: b/139424793 Change-Id: Idc197fb93c28cdc4b91174a687179f9fc498344a Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/35208 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent 42a034f6
......@@ -2276,18 +2276,19 @@ namespace sw
return; // Already emitted this loop.
}
std::unordered_set<Block::ID> incomingBlocks;
// Gather all the blocks that make up the loop.
std::unordered_set<Block::ID> loopBlocks;
loopBlocks.emplace(block.mergeBlock);
function.TraverseReachableBlocks(blockId, loopBlocks);
// incomingBlocks are block ins that are not back-edges.
std::unordered_set<Block::ID> incomingBlocks;
for (auto in : block.ins)
{
if (!function.ExistsPath(blockId, in, mergeBlockId)) // if not a loop back-edge
if (loopBlocks.count(in) == 0)
{
incomingBlocks.emplace(in);
}
else
{
loopBlocks.emplace(in);
}
}
// Emit the loop phi instructions, and initialize them with a value from
......@@ -2408,7 +2409,7 @@ namespace sw
{
if (insn.opcode() == spv::OpPhi)
{
StorePhi(mergeBlockId, insn, state, mergeBlock.ins);
StorePhi(mergeBlockId, insn, state, loopBlocks);
}
}
......@@ -6692,8 +6693,7 @@ namespace sw
}
}
void SpirvShader::Function::TraverseReachableBlocks(Block::ID id, SpirvShader::Block::Set& reachable)
void SpirvShader::Function::TraverseReachableBlocks(Block::ID id, SpirvShader::Block::Set& reachable) const
{
if (reachable.count(id) == 0)
{
......
......@@ -578,7 +578,7 @@ namespace sw
// Walks all reachable the blocks starting from id adding them to
// reachable.
void TraverseReachableBlocks(Block::ID id, Block::Set& reachable);
void TraverseReachableBlocks(Block::ID id, Block::Set& reachable) const;
// AssignBlockFields() performs the following for all reachable blocks:
// * Assigns Block::ins with the identifiers of all blocks that contain
......
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