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
+9 -17
View File
@@ -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<const Block*> blocks;
std::unordered_map<const Block*, size_t> block_indices;
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++) {
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<const Block*> 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<const Block*> 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<const Block*> 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<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) {
return dominators[block_indices.at(use)][block_indices.at(definition)];
};