Commit fe3f0136 by Ben Clayton

SpirvShader: Handle dead code branches.

Given the following situation: ``` >->- alive >->->-> \ >-> alive / unreachable >-> ``` We would attempt to codegen the dead block (all blocks ensure their in's are processed first). However dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_false_frag seems to have dead blocks that use values from blocks it couldn't possibly use (as it has no ins). While this is probably just a broken test, it is still good to harden up the compiler to pathological cases like this. Tests: dEQP-VK.spirv_assembly.instruction.compute.* Tests: dEQP-VK.spirv_assembly.instruction.graphics.* Bug: b/128527271 Change-Id: Ibaacf6a58cf7ab6e73771b58cfe67f0c394e53c6 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27948Tested-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent 20b950a2
...@@ -469,7 +469,27 @@ namespace sw ...@@ -469,7 +469,27 @@ namespace sw
} }
} }
// Assign all Block::ins MarkReachableBlocks(mainBlockId);
AssignBlockIns();
}
void SpirvShader::MarkReachableBlocks(Block::ID id)
{
auto it = blocks.find(id);
ASSERT_MSG(it != blocks.end(), "Unknown block %d", id.value());
auto &block = it->second;
if (!block.reachable)
{
block.reachable = true;
for (auto out : block.outs)
{
MarkReachableBlocks(out);
}
}
}
void SpirvShader::AssignBlockIns()
{
for (auto &it : blocks) for (auto &it : blocks)
{ {
auto &blockId = it.first; auto &blockId = it.first;
...@@ -1183,6 +1203,13 @@ namespace sw ...@@ -1183,6 +1203,13 @@ namespace sw
void SpirvShader::EmitBlock(Block::ID id, EmitState *state) const void SpirvShader::EmitBlock(Block::ID id, EmitState *state) const
{ {
auto &block = getBlock(id);
if (!block.reachable)
{
return;
}
if (state->visited.count(id) > 0) if (state->visited.count(id) > 0)
{ {
return; // Already processed this block. return; // Already processed this block.
...@@ -1190,8 +1217,6 @@ namespace sw ...@@ -1190,8 +1217,6 @@ namespace sw
state->visited.emplace(id); state->visited.emplace(id);
auto &block = getBlock(id);
switch (block.kind) switch (block.kind)
{ {
case Block::Simple: case Block::Simple:
...@@ -1207,7 +1232,7 @@ namespace sw ...@@ -1207,7 +1232,7 @@ namespace sw
for (auto in : block.ins) for (auto in : block.ins)
{ {
EmitBlock(in, state); EmitBlock(in, state);
auto inMask = state->getActiveLaneMaskEdge(in, id); auto inMask = GetActiveLaneMaskEdge(state, in, id);
activeLaneMask.replace(0, activeLaneMask.Int(0) | inMask); activeLaneMask.replace(0, activeLaneMask.Int(0) | inMask);
} }
state->setActiveLaneMask(activeLaneMask.Int(0)); state->setActiveLaneMask(activeLaneMask.Int(0));
...@@ -1257,7 +1282,7 @@ namespace sw ...@@ -1257,7 +1282,7 @@ namespace sw
if (!existsPath(blockId, in)) // if not a loop back edge if (!existsPath(blockId, in)) // if not a loop back edge
{ {
EmitBlock(in, state); EmitBlock(in, state);
loopActiveLaneMask |= state->getActiveLaneMaskEdge(in, blockId); loopActiveLaneMask |= GetActiveLaneMaskEdge(state, in, blockId);
} }
} }
...@@ -1310,7 +1335,7 @@ namespace sw ...@@ -1310,7 +1335,7 @@ namespace sw
for (uint32_t i = 0; i < type.sizeInComponents; i++) for (uint32_t i = 0; i < type.sizeInComponents; i++)
{ {
auto in = GenericValue(this, state->routine, varId); auto in = GenericValue(this, state->routine, varId);
auto mask = state->getActiveLaneMaskEdge(blockId, state->currentBlock); auto mask = GetActiveLaneMaskEdge(state, blockId, state->currentBlock);
phi.storage[i] = phi.storage[i] | (in.Int(i) & mask); phi.storage[i] = phi.storage[i] | (in.Int(i) & mask);
} }
} }
...@@ -1360,7 +1385,7 @@ namespace sw ...@@ -1360,7 +1385,7 @@ namespace sw
if (existsPath(blockId, in)) if (existsPath(blockId, in))
{ {
EmitBlock(in, state); EmitBlock(in, state);
loopActiveLaneMask |= state->getActiveLaneMaskEdge(in, blockId); loopActiveLaneMask |= GetActiveLaneMaskEdge(state, in, blockId);
} }
} }
...@@ -2956,7 +2981,7 @@ namespace sw ...@@ -2956,7 +2981,7 @@ namespace sw
auto blockId = Block::ID(insn.word(w + 1)); auto blockId = Block::ID(insn.word(w + 1));
auto in = GenericValue(this, routine, varId); auto in = GenericValue(this, routine, varId);
auto mask = state->getActiveLaneMaskEdge(blockId, state->currentBlock); auto mask = GetActiveLaneMaskEdge(state, blockId, state->currentBlock);
for (uint32_t i = 0; i < type.sizeInComponents; i++) for (uint32_t i = 0; i < type.sizeInComponents; i++)
{ {
...@@ -3130,11 +3155,16 @@ namespace sw ...@@ -3130,11 +3155,16 @@ namespace sw
} }
} }
RValue<SIMD::Int> SpirvShader::EmitState::getActiveLaneMaskEdge(Block::ID from, Block::ID to) RValue<SIMD::Int> SpirvShader::GetActiveLaneMaskEdge(EmitState *state, Block::ID from, Block::ID to) const
{
if (!getBlock(from).reachable)
{ {
return SIMD::Int(0);
}
auto edge = Block::Edge{from, to}; auto edge = Block::Edge{from, to};
auto it = edgeActiveLaneMasks.find(edge); auto it = state->edgeActiveLaneMasks.find(edge);
ASSERT_MSG(it != edgeActiveLaneMasks.end(), "Could not find edge %d -> %d", from.value(), to.value()); ASSERT_MSG(it != state->edgeActiveLaneMasks.end(), "Could not find edge %d -> %d", from.value(), to.value());
return it->second; return it->second;
} }
......
...@@ -304,12 +304,13 @@ namespace sw ...@@ -304,12 +304,13 @@ namespace sw
}; };
Kind kind; Kind kind;
InsnIterator mergeInstruction; // Merge instruction. InsnIterator mergeInstruction; // Structured control flow merge instruction.
InsnIterator branchInstruction; // InsnIterator branchInstruction; // Branch instruction.
ID mergeBlock; // Structured flow merge block. ID mergeBlock; // Structured flow merge block.
ID continueTarget; // Loop continue block. ID continueTarget; // Loop continue block.
Set ins; // Blocks that branch into this block. Set ins; // Blocks that branch into this block.
Set outs; // Blocks that this block branches to. Set outs; // Blocks that this block branches to.
bool reachable = false;
private: private:
InsnIterator begin_; InsnIterator begin_;
...@@ -480,6 +481,13 @@ namespace sw ...@@ -480,6 +481,13 @@ namespace sw
HandleMap<Block> blocks; HandleMap<Block> blocks;
Block::ID mainBlockId; // Block of the entry point function. Block::ID mainBlockId; // Block of the entry point function.
// Walks all reachable the blocks starting from id, and sets
// Block::reachable to true.
void MarkReachableBlocks(Block::ID id);
// Assigns Block::ins from Block::outs for every block.
void AssignBlockIns();
// DeclareType creates a Type for the given OpTypeX instruction, storing // DeclareType creates a Type for the given OpTypeX instruction, storing
// it into the types map. It is called from the analysis pass (constructor). // it into the types map. It is called from the analysis pass (constructor).
void DeclareType(InsnIterator insn); void DeclareType(InsnIterator insn);
...@@ -559,10 +567,6 @@ namespace sw ...@@ -559,10 +567,6 @@ namespace sw
// they will be ORed together. // they will be ORed together.
void addActiveLaneMaskEdge(Block::ID from, Block::ID to, RValue<SIMD::Int> mask); void addActiveLaneMaskEdge(Block::ID from, Block::ID to, RValue<SIMD::Int> mask);
// Lookup the active lane mask for the edge from -> to.
// Asserts if the edge does not exist.
RValue<SIMD::Int> getActiveLaneMaskEdge(Block::ID from, Block::ID to);
SpirvRoutine *routine = nullptr; // The current routine being built. SpirvRoutine *routine = nullptr; // The current routine being built.
rr::Value *activeLaneMaskValue = nullptr; // The current active lane mask. rr::Value *activeLaneMaskValue = nullptr; // The current active lane mask.
Block::ID currentBlock; // The current block being built. Block::ID currentBlock; // The current block being built.
...@@ -581,6 +585,11 @@ namespace sw ...@@ -581,6 +585,11 @@ namespace sw
// the 'from' block to the 'to' block. // the 'from' block to the 'to' block.
bool existsPath(Block::ID from, Block::ID to) const; bool existsPath(Block::ID from, Block::ID to) const;
// Lookup the active lane mask for the edge from -> to.
// If from is unreachable, then a mask of all zeros is returned.
// Asserts if from is reachable and the edge does not exist.
RValue<SIMD::Int> GetActiveLaneMaskEdge(EmitState *state, Block::ID from, Block::ID to) const;
void EmitBlock(Block::ID id, EmitState *state) const; void EmitBlock(Block::ID id, EmitState *state) const;
void EmitInstructions(InsnIterator begin, InsnIterator end, EmitState *state) const; void EmitInstructions(InsnIterator begin, InsnIterator end, EmitState *state) const;
void EmitLoop(EmitState *state) const; void EmitLoop(EmitState *state) const;
......
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