From 1617ee77e5c0f5fafcc61b610d47cc74ba685fcf Mon Sep 17 00:00:00 2001 From: nmzik Date: Thu, 24 Sep 2026 02:36:54 +0400 Subject: [PATCH] Share CFG reachability for descriptor bounds analysis --- .../recompiler/ir/passes/ResourceTracking.cpp | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp b/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp index 232262460..0867a7e78 100644 --- a/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp +++ b/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp @@ -512,6 +512,28 @@ private: } } + const Block* FindBlock(uint32_t id) const { + const auto info = std::ranges::find(m_program.block_info, id, &BlockInfo::id); + return info == m_program.block_info.end() + ? nullptr + : m_program.blocks[info - m_program.block_info.begin()]; + } + + bool CanReach(const Block* start, const Block* target, const Block* avoid) const { + std::vector pending {start}; + std::vector visited; + while (!pending.empty()) { + const auto* block = pending.back(); + pending.pop_back(); + if (block == nullptr || block == avoid || + std::ranges::find(visited, block) != visited.end()) continue; + if (block == target) return true; + visited.push_back(block); + for (const auto* next: block->ImmSuccessors()) pending.push_back(next); + } + return false; + } + Value BoundedLoopCount(Value key, const Block* use) const { const auto* phi = key.Resolve().TryInstruction(); if (m_shader_writes || phi == nullptr || phi->GetOpcode() != ValueOpcode::Phi || @@ -537,26 +559,6 @@ private: } if (!induction) return {}; - const auto find_block = [&](uint32_t id) -> const Block* { - const auto info = std::ranges::find(m_program.block_info, id, &BlockInfo::id); - return info == m_program.block_info.end() - ? nullptr - : m_program.blocks[info - m_program.block_info.begin()]; - }; - const auto reaches = [&](const Block* start, const Block* target, const Block* avoid) { - std::vector pending {start}; - std::vector visited; - while (!pending.empty()) { - const auto* block = pending.back(); - pending.pop_back(); - if (block == nullptr || block == avoid || - std::ranges::find(visited, block) != visited.end()) continue; - if (block == target) return true; - visited.push_back(block); - for (const auto* next: block->ImmSuccessors()) pending.push_back(next); - } - return false; - }; const auto contains = [&](auto&& self, Value value, const Inst* comparison) -> bool { value = value.Resolve(); if (value.TryInstruction() == comparison) return true; @@ -576,10 +578,10 @@ private: negated->GetOpcode() != ValueOpcode::LogicalNot || !contains(contains, negated->Arg(0), compare) || use == m_program.blocks[i] || - reaches(m_program.blocks.front(), use, m_program.blocks[i]) || - reaches(phi->Parent(), use, m_program.blocks[i]) || - reaches(find_block(info.terminator.true_block), use, phi->Parent()) || - !reaches(find_block(info.terminator.false_block), use, phi->Parent())) { + CanReach(m_program.blocks.front(), use, m_program.blocks[i]) || + CanReach(phi->Parent(), use, m_program.blocks[i]) || + CanReach(FindBlock(info.terminator.true_block), use, phi->Parent()) || + !CanReach(FindBlock(info.terminator.false_block), use, phi->Parent())) { continue; } return compare->Arg(1);