Share CFG reachability for descriptor bounds analysis

This commit is contained in:
nmzik
2026-09-24 02:36:54 +04:00
parent 66cc2fe26d
commit 1617ee77e5
@@ -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<const Block*> pending {start};
std::vector<const Block*> 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 { Value BoundedLoopCount(Value key, const Block* use) const {
const auto* phi = key.Resolve().TryInstruction(); const auto* phi = key.Resolve().TryInstruction();
if (m_shader_writes || phi == nullptr || phi->GetOpcode() != ValueOpcode::Phi || if (m_shader_writes || phi == nullptr || phi->GetOpcode() != ValueOpcode::Phi ||
@@ -537,26 +559,6 @@ private:
} }
if (!induction) return {}; 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<const Block*> pending {start};
std::vector<const Block*> 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 { const auto contains = [&](auto&& self, Value value, const Inst* comparison) -> bool {
value = value.Resolve(); value = value.Resolve();
if (value.TryInstruction() == comparison) return true; if (value.TryInstruction() == comparison) return true;
@@ -576,10 +578,10 @@ private:
negated->GetOpcode() != ValueOpcode::LogicalNot || negated->GetOpcode() != ValueOpcode::LogicalNot ||
!contains(contains, negated->Arg(0), compare) || !contains(contains, negated->Arg(0), compare) ||
use == m_program.blocks[i] || use == m_program.blocks[i] ||
reaches(m_program.blocks.front(), use, m_program.blocks[i]) || CanReach(m_program.blocks.front(), use, m_program.blocks[i]) ||
reaches(phi->Parent(), use, m_program.blocks[i]) || CanReach(phi->Parent(), use, m_program.blocks[i]) ||
reaches(find_block(info.terminator.true_block), use, phi->Parent()) || CanReach(FindBlock(info.terminator.true_block), use, phi->Parent()) ||
!reaches(find_block(info.terminator.false_block), use, phi->Parent())) { !CanReach(FindBlock(info.terminator.false_block), use, phi->Parent())) {
continue; continue;
} }
return compare->Arg(1); return compare->Arg(1);