mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-22 03:46:53 +02:00
shader: reuse CFG and validation lookups
This commit is contained in:
@@ -323,11 +323,10 @@ bool ResolveJumpTableEntryCount(const Decoder::Program& program, uint32_t before
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddUniqueTargetPc(std::vector<uint32_t>& targets, uint32_t target) {
|
void AddUnique(std::vector<uint32_t>& values, uint32_t value) {
|
||||||
if (std::find(targets.begin(), targets.end(), target) == targets.end()) {
|
if (std::find(values.begin(), values.end(), value) == values.end()) {
|
||||||
targets.push_back(target);
|
values.push_back(value);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScalarCodeWrittenInRange(const Decoder::Program& program, uint32_t begin_index,
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
const auto target_pc = (target_base + low) & ~3u;
|
const auto target_pc = (target_base + low) & ~3u;
|
||||||
AddUniqueTargetPc(targets, target_pc);
|
AddUnique(targets, target_pc);
|
||||||
selector_values.push_back(i * 8u);
|
selector_values.push_back(i * 8u);
|
||||||
selector_target_pcs.push_back(target_pc);
|
selector_target_pcs.push_back(target_pc);
|
||||||
}
|
}
|
||||||
@@ -507,7 +506,7 @@ bool ResolveSetpcDwordJumpTable(const Decoder::Program& program, uint32_t setpc_
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto target_pc = (target_base - offset) & ~3u;
|
const auto target_pc = (target_base - offset) & ~3u;
|
||||||
AddUniqueTargetPc(targets, target_pc);
|
AddUnique(targets, target_pc);
|
||||||
selector_values.push_back(i * 4u);
|
selector_values.push_back(i * 4u);
|
||||||
selector_target_pcs.push_back(target_pc);
|
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));
|
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> AllBlockIds(uint32_t count) {
|
||||||
std::vector<uint32_t> ids;
|
std::vector<uint32_t> ids;
|
||||||
ids.reserve(count);
|
ids.reserve(count);
|
||||||
@@ -995,6 +988,29 @@ void RecomputeAnalyses(Graph& graph) {
|
|||||||
ComputeComponents(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) {
|
uint32_t MoveBlockBefore(Graph& graph, uint32_t block_id, uint32_t before_id) {
|
||||||
if (block_id == before_id || block_id >= graph.blocks.size() ||
|
if (block_id == before_id || block_id >= graph.blocks.size() ||
|
||||||
before_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);
|
const auto id_map = ApplyBlockOrder(graph, std::move(new_blocks));
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return RemapId(block_id, id_map);
|
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> construct_predecessors;
|
||||||
std::vector<uint32_t> external_predecessors;
|
bool has_external_predecessor = false;
|
||||||
for (auto pred: merge_block->predecessors) {
|
for (auto pred: merge_block->predecessors) {
|
||||||
if (Contains(construct_blocks, pred)) {
|
if (Contains(construct_blocks, pred)) {
|
||||||
AddUnique(construct_predecessors, pred);
|
AddUnique(construct_predecessors, pred);
|
||||||
} else {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
const auto synthetic_merge = AppendSyntheticBranchBlock(graph, merge);
|
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]));
|
new_blocks.push_back(std::move(old_blocks[block_id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> id_map(new_blocks.size(), UINT32_MAX);
|
ApplyBlockOrder(graph, std::move(new_blocks));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AppendGotoSelectBlock(Graph& graph, uint32_t route_variable, uint32_t true_target,
|
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::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++) {
|
for (uint32_t i = 0; i < sorted_labels.size(); i++) {
|
||||||
const auto start = sorted_labels[i];
|
const auto start = sorted_labels[i];
|
||||||
if (start > end_pc) {
|
if (start > end_pc) {
|
||||||
|
|||||||
@@ -189,28 +189,27 @@ void ValidateProgram(const Program& program, bool require_ssa) {
|
|||||||
program.blocks.size() != program.block_storage.size()) {
|
program.blocks.size() != program.block_storage.size()) {
|
||||||
return Fail("value IR block storage is inconsistent");
|
return Fail("value IR block storage is inconsistent");
|
||||||
}
|
}
|
||||||
std::unordered_set<const Block*> blocks;
|
|
||||||
std::unordered_map<const Block*, size_t> block_indices;
|
std::unordered_map<const Block*, size_t> block_indices;
|
||||||
std::unordered_map<uint32_t, const Block*> blocks_by_id;
|
std::unordered_map<uint32_t, const Block*> blocks_by_id;
|
||||||
std::unordered_set<const Inst*> instructions;
|
std::unordered_map<const Inst*, size_t> instruction_positions;
|
||||||
for (size_t block_index = 0; block_index < program.blocks.size(); block_index++) {
|
for (size_t block_index = 0; block_index < program.blocks.size(); block_index++) {
|
||||||
const auto* block = program.blocks[block_index];
|
const auto* block = program.blocks[block_index];
|
||||||
if (block == nullptr || program.block_storage[block_index] == nullptr ||
|
if (block == nullptr || program.block_storage[block_index] == nullptr ||
|
||||||
block != program.block_storage[block_index].get()) {
|
block != program.block_storage[block_index].get()) {
|
||||||
return Fail("value IR block pointer is inconsistent");
|
return Fail("value IR block pointer is inconsistent");
|
||||||
}
|
}
|
||||||
if (!blocks.insert(block).second) {
|
if (!block_indices.emplace(block, block_index).second) {
|
||||||
return Fail("value IR block pointer is duplicated");
|
return Fail("value IR block pointer is duplicated");
|
||||||
}
|
}
|
||||||
block_indices.emplace(block, block_index);
|
|
||||||
if (program.block_info[block_index].id == UINT32_MAX) {
|
if (program.block_info[block_index].id == UINT32_MAX) {
|
||||||
return Fail("value IR block uses the reserved exit id");
|
return Fail("value IR block uses the reserved exit id");
|
||||||
}
|
}
|
||||||
if (!blocks_by_id.emplace(program.block_info[block_index].id, block).second) {
|
if (!blocks_by_id.emplace(program.block_info[block_index].id, block).second) {
|
||||||
return Fail("value IR block id is duplicated");
|
return Fail("value IR block id is duplicated");
|
||||||
}
|
}
|
||||||
|
size_t position = 0;
|
||||||
for (const auto& inst: *block) {
|
for (const auto& inst: *block) {
|
||||||
if (!instructions.insert(&inst).second) {
|
if (!instruction_positions.emplace(&inst, position++).second) {
|
||||||
return Fail("value IR instruction is duplicated");
|
return Fail("value IR instruction is duplicated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,7 +222,7 @@ void ValidateProgram(const Program& program, bool require_ssa) {
|
|||||||
const auto* block = program.blocks[block_index];
|
const auto* block = program.blocks[block_index];
|
||||||
std::unordered_set<const Block*> predecessors;
|
std::unordered_set<const Block*> predecessors;
|
||||||
for (const auto* predecessor: block->ImmPredecessors()) {
|
for (const auto* predecessor: block->ImmPredecessors()) {
|
||||||
if (predecessor == nullptr || !blocks.contains(predecessor)) {
|
if (predecessor == nullptr || !block_indices.contains(predecessor)) {
|
||||||
return Fail("value IR block has a foreign predecessor");
|
return Fail("value IR block has a foreign predecessor");
|
||||||
}
|
}
|
||||||
if (!predecessors.insert(predecessor).second) {
|
if (!predecessors.insert(predecessor).second) {
|
||||||
@@ -237,7 +236,7 @@ void ValidateProgram(const Program& program, bool require_ssa) {
|
|||||||
|
|
||||||
std::unordered_set<const Block*> successors;
|
std::unordered_set<const Block*> successors;
|
||||||
for (const auto* successor: block->ImmSuccessors()) {
|
for (const auto* successor: block->ImmSuccessors()) {
|
||||||
if (successor == nullptr || !blocks.contains(successor)) {
|
if (successor == nullptr || !block_indices.contains(successor)) {
|
||||||
return Fail("value IR block has a foreign successor");
|
return Fail("value IR block has a foreign successor");
|
||||||
}
|
}
|
||||||
if (!successors.insert(successor).second) {
|
if (!successors.insert(successor).second) {
|
||||||
@@ -264,7 +263,7 @@ void ValidateProgram(const Program& program, bool require_ssa) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto* definition = value.TryInstruction();
|
const auto* definition = value.TryInstruction();
|
||||||
return definition == nullptr || instructions.contains(definition);
|
return definition == nullptr || instruction_positions.contains(definition);
|
||||||
};
|
};
|
||||||
switch (terminator.kind) {
|
switch (terminator.kind) {
|
||||||
case CFG::TerminatorKind::Branch:
|
case CFG::TerminatorKind::Branch:
|
||||||
@@ -338,7 +337,7 @@ void ValidateProgram(const Program& program, bool require_ssa) {
|
|||||||
std::unordered_set<const Block*> incoming_blocks;
|
std::unordered_set<const Block*> incoming_blocks;
|
||||||
for (size_t arg_index = 0; arg_index < inst.NumArgs(); arg_index++) {
|
for (size_t arg_index = 0; arg_index < inst.NumArgs(); arg_index++) {
|
||||||
const auto* predecessor = inst.PhiBlock(arg_index);
|
const auto* predecessor = inst.PhiBlock(arg_index);
|
||||||
if (predecessor == nullptr || !blocks.contains(predecessor) ||
|
if (predecessor == nullptr || !block_indices.contains(predecessor) ||
|
||||||
!predecessors.contains(predecessor)) {
|
!predecessors.contains(predecessor)) {
|
||||||
return Fail("value IR Phi has a foreign or non-predecessor parent");
|
return Fail("value IR Phi has a foreign or non-predecessor parent");
|
||||||
}
|
}
|
||||||
@@ -520,7 +519,7 @@ void ValidateProgram(const Program& program, bool require_ssa) {
|
|||||||
TypeName(ArgTypeOf(inst.GetOpcode(), arg_index))));
|
TypeName(ArgTypeOf(inst.GetOpcode(), arg_index))));
|
||||||
}
|
}
|
||||||
if (const auto* definition = arg.TryInstruction();
|
if (const auto* definition = arg.TryInstruction();
|
||||||
definition != nullptr && !instructions.contains(definition)) {
|
definition != nullptr && !instruction_positions.contains(definition)) {
|
||||||
return Fail("value IR argument has a foreign definition");
|
return Fail("value IR argument has a foreign definition");
|
||||||
}
|
}
|
||||||
if (const auto* definition = arg.TryInstruction(); definition != nullptr) {
|
if (const auto* definition = arg.TryInstruction(); definition != nullptr) {
|
||||||
@@ -582,13 +581,6 @@ void ValidateProgram(const Program& program, bool require_ssa) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<const Inst*, size_t> instruction_positions;
|
|
||||||
for (const auto* block: program.blocks) {
|
|
||||||
size_t position = 0;
|
|
||||||
for (const auto& inst: *block) {
|
|
||||||
instruction_positions.emplace(&inst, position++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto dominates = [&](const Block* definition, const Block* use) {
|
const auto dominates = [&](const Block* definition, const Block* use) {
|
||||||
return dominators[block_indices.at(use)][block_indices.at(definition)];
|
return dominators[block_indices.at(use)][block_indices.at(definition)];
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user