shader: reuse CFG and validation lookups

This commit is contained in:
nmzik
2026-09-08 13:09:27 +04:00
parent 6f66f77b09
commit de3e86791c
2 changed files with 42 additions and 69 deletions
@@ -323,11 +323,10 @@ bool ResolveJumpTableEntryCount(const Decoder::Program& program, uint32_t before
return false;
}
bool AddUniqueTargetPc(std::vector<uint32_t>& targets, uint32_t target) {
if (std::find(targets.begin(), targets.end(), target) == targets.end()) {
targets.push_back(target);
void AddUnique(std::vector<uint32_t>& values, uint32_t value) {
if (std::find(values.begin(), values.end(), value) == values.end()) {
values.push_back(value);
}
return true;
}
bool ScalarCodeWrittenInRange(const Decoder::Program& program, uint32_t begin_index,
@@ -421,7 +420,7 @@ bool ResolveSetpcJumpTable(const Decoder::Program& program, uint32_t setpc_index
return false;
}
const auto target_pc = (target_base + low) & ~3u;
AddUniqueTargetPc(targets, target_pc);
AddUnique(targets, target_pc);
selector_values.push_back(i * 8u);
selector_target_pcs.push_back(target_pc);
}
@@ -507,7 +506,7 @@ bool ResolveSetpcDwordJumpTable(const Decoder::Program& program, uint32_t setpc_
return false;
}
const auto target_pc = (target_base - offset) & ~3u;
AddUniqueTargetPc(targets, target_pc);
AddUnique(targets, target_pc);
selector_values.push_back(i * 4u);
selector_target_pcs.push_back(target_pc);
}
@@ -590,12 +589,6 @@ bool IsValidTarget(uint32_t target, const std::set<uint32_t>& instruction_pcs, u
return target == end_pc || (target >= first_pc && instruction_pcs.contains(target));
}
void AddUnique(std::vector<uint32_t>& values, uint32_t value) {
if (std::find(values.begin(), values.end(), value) == values.end()) {
values.push_back(value);
}
}
std::vector<uint32_t> AllBlockIds(uint32_t count) {
std::vector<uint32_t> ids;
ids.reserve(count);
@@ -995,6 +988,29 @@ void RecomputeAnalyses(Graph& graph) {
ComputeComponents(graph);
}
std::vector<uint32_t> ApplyBlockOrder(Graph& graph, std::vector<BasicBlock> blocks) {
std::vector<uint32_t> id_map(blocks.size(), UINT32_MAX);
for (uint32_t i = 0; i < blocks.size(); i++) {
id_map[blocks[i].id] = i;
}
graph.blocks = std::move(blocks);
graph.entry_block = RemapId(graph.entry_block, id_map);
for (auto& block: graph.blocks) {
block.id = RemapId(block.id, id_map);
RemapIds(block.predecessors, id_map);
RemapIds(block.successors, id_map);
RemapIds(block.dominators, id_map);
RemapIds(block.post_dominators, id_map);
block.terminator.true_block = RemapId(block.terminator.true_block, id_map);
block.terminator.false_block = RemapId(block.terminator.false_block, id_map);
block.terminator.merge_block = RemapId(block.terminator.merge_block, id_map);
block.terminator.continue_block = RemapId(block.terminator.continue_block, id_map);
}
return id_map;
}
uint32_t MoveBlockBefore(Graph& graph, uint32_t block_id, uint32_t before_id) {
if (block_id == before_id || block_id >= graph.blocks.size() ||
before_id >= graph.blocks.size()) {
@@ -1016,24 +1032,7 @@ uint32_t MoveBlockBefore(Graph& graph, uint32_t block_id, uint32_t before_id) {
}
}
std::vector<uint32_t> id_map(new_blocks.size(), UINT32_MAX);
for (uint32_t i = 0; i < new_blocks.size(); i++) {
id_map[new_blocks[i].id] = i;
}
graph.blocks = std::move(new_blocks);
graph.entry_block = RemapId(graph.entry_block, id_map);
for (auto& block: graph.blocks) {
block.id = RemapId(block.id, id_map);
RemapIds(block.predecessors, id_map);
RemapIds(block.successors, id_map);
RemapIds(block.dominators, id_map);
RemapIds(block.post_dominators, id_map);
block.terminator.true_block = RemapId(block.terminator.true_block, id_map);
block.terminator.false_block = RemapId(block.terminator.false_block, id_map);
block.terminator.merge_block = RemapId(block.terminator.merge_block, id_map);
block.terminator.continue_block = RemapId(block.terminator.continue_block, id_map);
}
const auto id_map = ApplyBlockOrder(graph, std::move(new_blocks));
return RemapId(block_id, id_map);
}
@@ -1396,16 +1395,16 @@ bool SplitSharedMergeBlock(Graph& graph, uint32_t merge,
}
std::vector<uint32_t> construct_predecessors;
std::vector<uint32_t> external_predecessors;
bool has_external_predecessor = false;
for (auto pred: merge_block->predecessors) {
if (Contains(construct_blocks, pred)) {
AddUnique(construct_predecessors, pred);
} else {
AddUnique(external_predecessors, pred);
has_external_predecessor = true;
}
}
if (construct_predecessors.empty() || (!force_split && external_predecessors.empty())) {
if (construct_predecessors.empty() || (!force_split && !has_external_predecessor)) {
return false;
}
const auto synthetic_merge = AppendSyntheticBranchBlock(graph, merge);
@@ -1656,24 +1655,7 @@ void PlaceGotoRouteBlocks(Graph& graph, uint32_t original_block_count,
new_blocks.push_back(std::move(old_blocks[block_id]));
}
std::vector<uint32_t> id_map(new_blocks.size(), UINT32_MAX);
for (uint32_t block_id = 0; block_id < new_blocks.size(); block_id++) {
id_map[new_blocks[block_id].id] = block_id;
}
graph.blocks = std::move(new_blocks);
graph.entry_block = RemapId(graph.entry_block, id_map);
for (auto& block: graph.blocks) {
block.id = RemapId(block.id, id_map);
RemapIds(block.predecessors, id_map);
RemapIds(block.successors, id_map);
RemapIds(block.dominators, id_map);
RemapIds(block.post_dominators, id_map);
block.terminator.true_block = RemapId(block.terminator.true_block, id_map);
block.terminator.false_block = RemapId(block.terminator.false_block, id_map);
block.terminator.merge_block = RemapId(block.terminator.merge_block, id_map);
block.terminator.continue_block = RemapId(block.terminator.continue_block, id_map);
}
ApplyBlockOrder(graph, std::move(new_blocks));
}
uint32_t AppendGotoSelectBlock(Graph& graph, uint32_t route_variable, uint32_t true_target,
@@ -1981,7 +1963,6 @@ Graph BuildGraph(const Decoder::Program& program) {
}
std::vector<uint32_t> sorted_labels(labels.begin(), labels.end());
std::sort(sorted_labels.begin(), sorted_labels.end());
for (uint32_t i = 0; i < sorted_labels.size(); i++) {
const auto start = sorted_labels[i];
if (start > end_pc) {