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 ...@@ -2276,18 +2276,19 @@ namespace sw
return; // Already emitted this loop. 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; 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) 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); incomingBlocks.emplace(in);
} }
else
{
loopBlocks.emplace(in);
}
} }
// Emit the loop phi instructions, and initialize them with a value from // Emit the loop phi instructions, and initialize them with a value from
...@@ -2408,7 +2409,7 @@ namespace sw ...@@ -2408,7 +2409,7 @@ namespace sw
{ {
if (insn.opcode() == spv::OpPhi) if (insn.opcode() == spv::OpPhi)
{ {
StorePhi(mergeBlockId, insn, state, mergeBlock.ins); StorePhi(mergeBlockId, insn, state, loopBlocks);
} }
} }
...@@ -6692,8 +6693,7 @@ namespace sw ...@@ -6692,8 +6693,7 @@ namespace sw
} }
} }
void SpirvShader::Function::TraverseReachableBlocks(Block::ID id, SpirvShader::Block::Set& reachable) const
void SpirvShader::Function::TraverseReachableBlocks(Block::ID id, SpirvShader::Block::Set& reachable)
{ {
if (reachable.count(id) == 0) if (reachable.count(id) == 0)
{ {
......
...@@ -578,7 +578,7 @@ namespace sw ...@@ -578,7 +578,7 @@ namespace sw
// Walks all reachable the blocks starting from id adding them to // Walks all reachable the blocks starting from id adding them to
// reachable. // 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: // AssignBlockFields() performs the following for all reachable blocks:
// * Assigns Block::ins with the identifiers of all blocks that contain // * 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