shader: Fix splits on blocks using indirect branches

This commit is contained in:
ReinUsesLisp 2021-04-04 20:00:34 -03:00 committed by ameerj
parent ffca21487f
commit 9e6fe430bd
3 changed files with 38 additions and 17 deletions

View file

@ -45,19 +45,29 @@ void Split(Block* old_block, Block* new_block, Location pc) {
.begin{pc}, .begin{pc},
.end{old_block->end}, .end{old_block->end},
.end_class{old_block->end_class}, .end_class{old_block->end_class},
.stack{old_block->stack},
.cond{old_block->cond}, .cond{old_block->cond},
.stack{old_block->stack},
.branch_true{old_block->branch_true}, .branch_true{old_block->branch_true},
.branch_false{old_block->branch_false}, .branch_false{old_block->branch_false},
.function_call{old_block->function_call},
.return_block{old_block->return_block},
.branch_reg{old_block->branch_reg},
.branch_offset{old_block->branch_offset},
.indirect_branches{std::move(old_block->indirect_branches)},
}; };
*old_block = Block{ *old_block = Block{
.begin{old_block->begin}, .begin{old_block->begin},
.end{pc}, .end{pc},
.end_class{EndClass::Branch}, .end_class{EndClass::Branch},
.stack{std::move(old_block->stack)},
.cond{true}, .cond{true},
.stack{std::move(old_block->stack)},
.branch_true{new_block}, .branch_true{new_block},
.branch_false{nullptr}, .branch_false{nullptr},
.function_call{},
.return_block{},
.branch_reg{},
.branch_offset{},
.indirect_branches{},
}; };
} }
@ -173,10 +183,15 @@ Function::Function(ObjectPool<Block>& block_pool, Location start_address)
.begin{start_address}, .begin{start_address},
.end{start_address}, .end{start_address},
.end_class{EndClass::Branch}, .end_class{EndClass::Branch},
.stack{},
.cond{true}, .cond{true},
.stack{},
.branch_true{nullptr}, .branch_true{nullptr},
.branch_false{nullptr}, .branch_false{nullptr},
.function_call{},
.return_block{},
.branch_reg{},
.branch_offset{},
.indirect_branches{},
})}, })},
.stack{}, .stack{},
}} {} }} {}
@ -351,10 +366,15 @@ void CFG::AnalyzeCondInst(Block* block, FunctionId function_id, Location pc,
.begin{block->begin.Virtual()}, .begin{block->begin.Virtual()},
.end{block->begin.Virtual()}, .end{block->begin.Virtual()},
.end_class{EndClass::Branch}, .end_class{EndClass::Branch},
.stack{block->stack},
.cond{cond}, .cond{cond},
.stack{block->stack},
.branch_true{conditional_block}, .branch_true{conditional_block},
.branch_false{nullptr}, .branch_false{nullptr},
.function_call{},
.return_block{},
.branch_reg{},
.branch_offset{},
.indirect_branches{},
}; };
// Save the contents of the visited block in the conditional block // Save the contents of the visited block in the conditional block
*conditional_block = std::move(*block); *conditional_block = std::move(*block);
@ -502,10 +522,15 @@ Block* CFG::AddLabel(Block* block, Stack stack, Location pc, FunctionId function
.begin{pc}, .begin{pc},
.end{pc}, .end{pc},
.end_class{EndClass::Branch}, .end_class{EndClass::Branch},
.stack{stack},
.cond{true}, .cond{true},
.stack{stack},
.branch_true{nullptr}, .branch_true{nullptr},
.branch_false{nullptr}, .branch_false{nullptr},
.function_call{},
.return_block{},
.branch_reg{},
.branch_offset{},
.indirect_branches{},
})}; })};
function.labels.push_back(Label{ function.labels.push_back(Label{
.address{pc}, .address{pc},

View file

@ -79,18 +79,14 @@ struct Block : boost::intrusive::set_base_hook<
Location begin; Location begin;
Location end; Location end;
EndClass end_class; EndClass end_class;
Stack stack;
IR::Condition cond; IR::Condition cond;
union { Stack stack;
Block* branch_true; Block* branch_true;
FunctionId function_call;
IR::Reg branch_reg;
};
union {
Block* branch_false; Block* branch_false;
FunctionId function_call;
Block* return_block; Block* return_block;
IR::Reg branch_reg;
s32 branch_offset; s32 branch_offset;
};
std::vector<IndirectBranch> indirect_branches; std::vector<IndirectBranch> indirect_branches;
}; };

View file

@ -21,7 +21,7 @@ void RemoveUnreachableBlocks(IR::Program& program) {
if (program.blocks.size() == program.post_order_blocks.size()) { if (program.blocks.size() == program.post_order_blocks.size()) {
return; return;
} }
const auto begin{std::next(program.blocks.begin())}; const auto begin{program.blocks.begin() + 1};
const auto end{program.blocks.end()}; const auto end{program.blocks.end()};
const auto pred{[](IR::Block* block) { return block->ImmediatePredecessors().empty(); }}; const auto pred{[](IR::Block* block) { return block->ImmediatePredecessors().empty(); }};
program.blocks.erase(std::remove_if(begin, end, pred), end); program.blocks.erase(std::remove_if(begin, end, pred), end);