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: Nicolas Capens <nicolascapens@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index f9a1572..061d9cf 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -2276,18 +2276,19 @@
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 @@
{
if (insn.opcode() == spv::OpPhi)
{
- StorePhi(mergeBlockId, insn, state, mergeBlock.ins);
+ StorePhi(mergeBlockId, insn, state, loopBlocks);
}
}
@@ -6692,8 +6693,7 @@
}
}
-
- 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)
{
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 412d7a2..6d77117 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -578,7 +578,7 @@
// 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