Added block.cases_32bit and reworked the cases fix
Now we added block.cases_32bit as requested and we only parse if the remaining ops are a multiple of 2. None of them are mutable because we return a reference of them depending of the op.condition width. Signed-off-by: Sebastián Aedo <saedo@codeweavers.com>
This commit is contained in:
parent
03f678dec4
commit
75e3752273
@ -135,8 +135,9 @@ bool CFG::post_order_visit(uint32_t block_id)
|
||||
break;
|
||||
|
||||
case SPIRBlock::MultiSelect:
|
||||
compiler.fix_switch_branches(block);
|
||||
for (auto &target : block.cases)
|
||||
{
|
||||
const auto &cases = compiler.get_case_list(block);
|
||||
for (const auto &target : cases)
|
||||
{
|
||||
if (post_order_visit(target.block))
|
||||
add_branch(block_id, target.block);
|
||||
@ -144,6 +145,7 @@ bool CFG::post_order_visit(uint32_t block_id)
|
||||
if (block.default_block && post_order_visit(block.default_block))
|
||||
add_branch(block_id, block.default_block);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -385,7 +387,9 @@ void DominatorBuilder::lift_continue_block_dominator()
|
||||
break;
|
||||
|
||||
case SPIRBlock::MultiSelect:
|
||||
for (auto &target : block.cases)
|
||||
{
|
||||
auto &cases = cfg.get_compiler().get_case_list(block);
|
||||
for (auto &target : cases)
|
||||
{
|
||||
if (cfg.get_visit_order(target.block) > post_order)
|
||||
back_edge_dominator = true;
|
||||
@ -393,6 +397,7 @@ void DominatorBuilder::lift_continue_block_dominator()
|
||||
if (block.default_block && cfg.get_visit_order(block.default_block) > post_order)
|
||||
back_edge_dominator = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -857,7 +857,7 @@ struct SPIRBlock : IVariant
|
||||
uint64_t value;
|
||||
BlockID block;
|
||||
};
|
||||
mutable SmallVector<Case> cases;
|
||||
SmallVector<Case> cases_32bit;
|
||||
SmallVector<Case> cases_64bit;
|
||||
|
||||
// If we have tried to optimize code for this block but failed,
|
||||
|
@ -1626,7 +1626,7 @@ SPIRBlock::ContinueBlockType Compiler::continue_block_type(const SPIRBlock &bloc
|
||||
}
|
||||
}
|
||||
|
||||
void Compiler::fix_switch_branches(const SPIRBlock &block) const
|
||||
const SmallVector<SPIRBlock::Case> &Compiler::get_case_list(const SPIRBlock &block) const
|
||||
{
|
||||
auto search = ir.load_type_width.find(block.condition);
|
||||
if (search == ir.load_type_width.end())
|
||||
@ -1636,7 +1636,9 @@ void Compiler::fix_switch_branches(const SPIRBlock &block) const
|
||||
|
||||
const uint32_t width = search->second;
|
||||
if (width > 32)
|
||||
block.cases = std::move(block.cases_64bit);
|
||||
return block.cases_64bit;
|
||||
|
||||
return block.cases_32bit;
|
||||
}
|
||||
|
||||
bool Compiler::traverse_all_reachable_opcodes(const SPIRBlock &block, OpcodeHandler &handler) const
|
||||
@ -3025,12 +3027,15 @@ void Compiler::AnalyzeVariableScopeAccessHandler::set_current_block(const SPIRBl
|
||||
break;
|
||||
|
||||
case SPIRBlock::MultiSelect:
|
||||
{
|
||||
notify_variable_access(block.condition, block.self);
|
||||
for (auto &target : block.cases)
|
||||
auto &cases = compiler.get_case_list(block);
|
||||
for (auto &target : cases)
|
||||
test_phi(target.block);
|
||||
if (block.default_block)
|
||||
test_phi(block.default_block);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -1117,7 +1117,11 @@ protected:
|
||||
uint32_t evaluate_constant_u32(uint32_t id) const;
|
||||
|
||||
bool is_vertex_like_shader() const;
|
||||
void fix_switch_branches(const SPIRBlock &block) const;
|
||||
|
||||
// Get the correct case list for the OpSwitch, since it can be either a
|
||||
// 32 bit wide condition or a 64 bit, but the type is not embedded in the
|
||||
// instruction itself.
|
||||
const SmallVector<SPIRBlock::Case> &get_case_list(const SPIRBlock &block) const;
|
||||
|
||||
private:
|
||||
// Used only to implement the old deprecated get_entry_point() interface.
|
||||
|
@ -14789,7 +14789,8 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
||||
// and let the default: block handle it.
|
||||
// 2.11 in SPIR-V spec states that for fall-through cases, there is a very strict declaration order which we can take advantage of here.
|
||||
// We only need to consider possible fallthrough if order[i] branches to order[i + 1].
|
||||
for (auto &c : block.cases)
|
||||
auto &cases = get_case_list(block);
|
||||
for (auto &c : cases)
|
||||
{
|
||||
// It's safe to cast to uint32_t since we actually do a check
|
||||
// previously that we're not using uint64_t as the switch selector.
|
||||
@ -14925,7 +14926,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
||||
// If there is only one default block, and no cases, this is a case where SPIRV-opt decided to emulate
|
||||
// non-structured exits with the help of a switch block.
|
||||
// This is buggy on FXC, so just emit the logical equivalent of a do { } while(false), which is more idiomatic.
|
||||
bool degenerate_switch = block.default_block != block.merge_block && block.cases.empty();
|
||||
bool degenerate_switch = block.default_block != block.merge_block && block.cases_32bit.empty();
|
||||
|
||||
if (degenerate_switch || is_legacy_es())
|
||||
{
|
||||
|
@ -979,15 +979,20 @@ void Parser::parse(const Instruction &instruction)
|
||||
current_block->default_block = ops[1];
|
||||
|
||||
uint32_t remaining_ops = length - 2;
|
||||
for (uint32_t i = 2; i + 2 <= length; i += 2)
|
||||
current_block->cases.push_back({ ops[i], ops[i + 1] });
|
||||
if ((remaining_ops % 2) == 0)
|
||||
{
|
||||
for (uint32_t i = 2; i + 2 <= length; i += 2)
|
||||
current_block->cases_32bit.push_back({ ops[i], ops[i + 1] });
|
||||
}
|
||||
|
||||
if ((remaining_ops % 3) == 0)
|
||||
{
|
||||
for (uint32_t i = 2; i + 3 <= length; i += 3)
|
||||
{
|
||||
uint64_t value = (static_cast<uint64_t>(ops[i]) << 32) | ops[i + 1];
|
||||
current_block->cases_64bit.push_back({ value, ops[i + 2] });
|
||||
}
|
||||
}
|
||||
|
||||
// If we jump to next block, make it break instead since we're inside a switch case block at that point.
|
||||
ir.block_meta[current_block->next_block] |= ParsedIR::BLOCK_META_MULTISELECT_MERGE_BIT;
|
||||
@ -1145,7 +1150,7 @@ void Parser::parse(const Instruction &instruction)
|
||||
// Actual opcodes.
|
||||
default:
|
||||
{
|
||||
if (ops)
|
||||
if (length >= 2)
|
||||
{
|
||||
const auto *type = maybe_get<SPIRType>(ops[0]);
|
||||
if (type)
|
||||
|
Loading…
Reference in New Issue
Block a user