forked from suyu/suyu
shader: Fix indirect branches to scheduler instructions
This commit is contained in:
parent
55b960a20f
commit
b0d5572abf
3 changed files with 17 additions and 7 deletions
|
@ -434,7 +434,10 @@ CFG::AnalysisState CFG::AnalyzeBRX(Block* block, Location pc, Instruction inst,
|
||||||
block->indirect_branches.reserve(targets.size());
|
block->indirect_branches.reserve(targets.size());
|
||||||
for (const u32 target : targets) {
|
for (const u32 target : targets) {
|
||||||
Block* const branch{AddLabel(block, block->stack, target, function_id)};
|
Block* const branch{AddLabel(block, block->stack, target, function_id)};
|
||||||
block->indirect_branches.push_back(branch);
|
block->indirect_branches.push_back({
|
||||||
|
.block{branch},
|
||||||
|
.address{target},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
block->cond = IR::Condition{true};
|
block->cond = IR::Condition{true};
|
||||||
block->end = pc + 1;
|
block->end = pc + 1;
|
||||||
|
@ -530,8 +533,8 @@ std::string CFG::Dot() const {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EndClass::IndirectBranch:
|
case EndClass::IndirectBranch:
|
||||||
for (Block* const branch : block.indirect_branches) {
|
for (const IndirectBranch& branch : block.indirect_branches) {
|
||||||
add_branch(branch, false);
|
add_branch(branch.block, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EndClass::Call:
|
case EndClass::Call:
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
namespace Shader::Maxwell::Flow {
|
namespace Shader::Maxwell::Flow {
|
||||||
|
|
||||||
|
struct Block;
|
||||||
|
|
||||||
using FunctionId = size_t;
|
using FunctionId = size_t;
|
||||||
|
|
||||||
enum class EndClass {
|
enum class EndClass {
|
||||||
|
@ -60,6 +62,11 @@ private:
|
||||||
boost::container::small_vector<StackEntry, 3> entries;
|
boost::container::small_vector<StackEntry, 3> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IndirectBranch {
|
||||||
|
Block* block;
|
||||||
|
u32 address;
|
||||||
|
};
|
||||||
|
|
||||||
struct Block : boost::intrusive::set_base_hook<
|
struct Block : boost::intrusive::set_base_hook<
|
||||||
// Normal link is ~2.5% faster compared to safe link
|
// Normal link is ~2.5% faster compared to safe link
|
||||||
boost::intrusive::link_mode<boost::intrusive::normal_link>> {
|
boost::intrusive::link_mode<boost::intrusive::normal_link>> {
|
||||||
|
@ -84,7 +91,7 @@ struct Block : boost::intrusive::set_base_hook<
|
||||||
Block* return_block;
|
Block* return_block;
|
||||||
s32 branch_offset;
|
s32 branch_offset;
|
||||||
};
|
};
|
||||||
std::vector<Block*> indirect_branches;
|
std::vector<IndirectBranch> indirect_branches;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Label {
|
struct Label {
|
||||||
|
|
|
@ -446,9 +446,9 @@ private:
|
||||||
case Flow::EndClass::IndirectBranch:
|
case Flow::EndClass::IndirectBranch:
|
||||||
root.insert(ip, *pool.Create(SetIndirectBranchVariable{}, block.branch_reg,
|
root.insert(ip, *pool.Create(SetIndirectBranchVariable{}, block.branch_reg,
|
||||||
block.branch_offset));
|
block.branch_offset));
|
||||||
for (Flow::Block* const branch : block.indirect_branches) {
|
for (const Flow::IndirectBranch& indirect : block.indirect_branches) {
|
||||||
const Node indirect_label{local_labels.at(branch)};
|
const Node indirect_label{local_labels.at(indirect.block)};
|
||||||
Statement* cond{pool.Create(IndirectBranchCond{}, branch->begin.Offset())};
|
Statement* cond{pool.Create(IndirectBranchCond{}, indirect.address)};
|
||||||
Statement* goto_stmt{pool.Create(Goto{}, cond, indirect_label, &root_stmt)};
|
Statement* goto_stmt{pool.Create(Goto{}, cond, indirect_label, &root_stmt)};
|
||||||
gotos.push_back(root.insert(ip, *goto_stmt));
|
gotos.push_back(root.insert(ip, *goto_stmt));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue