diff --git a/src/graphics/shader/recompiler/frontend/cfg/ShaderCFG.cpp b/src/graphics/shader/recompiler/frontend/cfg/ShaderCFG.cpp index 670e4e55..64e8e48b 100644 --- a/src/graphics/shader/recompiler/frontend/cfg/ShaderCFG.cpp +++ b/src/graphics/shader/recompiler/frontend/cfg/ShaderCFG.cpp @@ -323,11 +323,10 @@ bool ResolveJumpTableEntryCount(const Decoder::Program& program, uint32_t before return false; } -bool AddUniqueTargetPc(std::vector& targets, uint32_t target) { - if (std::find(targets.begin(), targets.end(), target) == targets.end()) { - targets.push_back(target); +void AddUnique(std::vector& 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& instruction_pcs, u return target == end_pc || (target >= first_pc && instruction_pcs.contains(target)); } -void AddUnique(std::vector& values, uint32_t value) { - if (std::find(values.begin(), values.end(), value) == values.end()) { - values.push_back(value); - } -} - std::vector AllBlockIds(uint32_t count) { std::vector ids; ids.reserve(count); @@ -995,6 +988,29 @@ void RecomputeAnalyses(Graph& graph) { ComputeComponents(graph); } +std::vector ApplyBlockOrder(Graph& graph, std::vector blocks) { + std::vector 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 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 construct_predecessors; - std::vector 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 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 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) { diff --git a/src/graphics/shader/recompiler/ir/Program.cpp b/src/graphics/shader/recompiler/ir/Program.cpp index ef71877b..9d834e13 100644 --- a/src/graphics/shader/recompiler/ir/Program.cpp +++ b/src/graphics/shader/recompiler/ir/Program.cpp @@ -189,28 +189,27 @@ void ValidateProgram(const Program& program, bool require_ssa) { program.blocks.size() != program.block_storage.size()) { return Fail("value IR block storage is inconsistent"); } - std::unordered_set blocks; std::unordered_map block_indices; std::unordered_map blocks_by_id; - std::unordered_set instructions; + std::unordered_map instruction_positions; for (size_t block_index = 0; block_index < program.blocks.size(); block_index++) { const auto* block = program.blocks[block_index]; if (block == nullptr || program.block_storage[block_index] == nullptr || block != program.block_storage[block_index].get()) { 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"); } - block_indices.emplace(block, block_index); if (program.block_info[block_index].id == UINT32_MAX) { return Fail("value IR block uses the reserved exit id"); } if (!blocks_by_id.emplace(program.block_info[block_index].id, block).second) { return Fail("value IR block id is duplicated"); } + size_t position = 0; for (const auto& inst: *block) { - if (!instructions.insert(&inst).second) { + if (!instruction_positions.emplace(&inst, position++).second) { 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]; std::unordered_set predecessors; 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"); } if (!predecessors.insert(predecessor).second) { @@ -237,7 +236,7 @@ void ValidateProgram(const Program& program, bool require_ssa) { std::unordered_set successors; 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"); } if (!successors.insert(successor).second) { @@ -264,7 +263,7 @@ void ValidateProgram(const Program& program, bool require_ssa) { return false; } const auto* definition = value.TryInstruction(); - return definition == nullptr || instructions.contains(definition); + return definition == nullptr || instruction_positions.contains(definition); }; switch (terminator.kind) { case CFG::TerminatorKind::Branch: @@ -338,7 +337,7 @@ void ValidateProgram(const Program& program, bool require_ssa) { std::unordered_set incoming_blocks; for (size_t arg_index = 0; arg_index < inst.NumArgs(); 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)) { 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)))); } 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"); } if (const auto* definition = arg.TryInstruction(); definition != nullptr) { @@ -582,13 +581,6 @@ void ValidateProgram(const Program& program, bool require_ssa) { } } - std::unordered_map 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) { return dominators[block_indices.at(use)][block_indices.at(definition)]; };