Files
VulkanDriver/src/compiler/ir/validator/dominance.zig
T
kbz_8 948e8b86a3
Mirror Gitea refs to GitHub / mirror (push) Successful in 18s
Test / build_and_test (push) Successful in 6m17s
Build / build (push) Successful in 7m51s
[Flint] adding IR lowering and printer
[IR] switching from "passes" to "transformers" for clarity
2026-07-29 15:39:41 +02:00

94 lines
3.2 KiB
Zig

const std = @import("std");
const cfg = @import("../cfg.zig");
const ids = @import("../id.zig");
const module_ir = @import("../module.zig");
pub const Error = std.mem.Allocator.Error || error{
InvalidBlock,
DefinitionDoesNotDominateUse,
};
const DominanceUseContext = struct {
module: *const module_ir.Module,
analysis: *const cfg,
function_id: ids.FunctionId,
use_block: ids.BlockId,
use_index: usize,
valid: bool = true,
};
pub fn validate(module: *const module_ir.Module, function_id: ids.FunctionId) Error!void {
var analysis = cfg.init(module.backingAllocator(), module, function_id) catch |err| switch (err) {
std.mem.Allocator.Error.OutOfMemory => return Error.OutOfMemory,
else => return Error.InvalidBlock,
};
defer analysis.deinit();
const function = module.functions.get(function_id).?;
for (function.blocks.items) |block_id| {
const block = module.blocks.get(block_id).?;
for (block.instructions.items, 0..) |instruction_id, instruction_index| {
const instruction = module.instructions.get(instruction_id).?;
var context: DominanceUseContext = .{
.module = module,
.analysis = &analysis,
.function_id = function_id,
.use_block = block_id,
.use_index = instruction_index,
};
instruction.operation.visitValueUses(&context, checkDominanceUse);
if (!context.valid)
return Error.DefinitionDoesNotDominateUse;
}
var context: DominanceUseContext = .{
.module = module,
.analysis = &analysis,
.function_id = function_id,
.use_block = block_id,
.use_index = block.instructions.items.len,
};
module_ir.visitTerminatorValueUses(block.terminator.?, &context, checkDominanceUse);
if (!context.valid)
return Error.DefinitionDoesNotDominateUse;
}
}
fn checkDominanceUse(context: *DominanceUseContext, value_id: ids.ValueId) void {
if (!context.valid)
return;
const value = context.module.values.get(value_id) orelse {
context.valid = false;
return;
};
context.valid = switch (value.definition) {
.constant, .undef => true,
.function_parameter => |definition| definition.function == context.function_id,
.block_parameter => |definition| context.analysis.dominates(definition.block, context.use_block),
.instruction => |instruction_id| blk: {
const definition = context.module.instructions.get(instruction_id) orelse break :blk false;
if (!context.analysis.dominates(definition.parent_block, context.use_block))
break :blk false;
if (definition.parent_block != context.use_block)
break :blk true;
const block = context.module.blocks.get(context.use_block) orelse break :blk false;
for (block.instructions.items, 0..) |candidate, definition_index| {
if (candidate == instruction_id)
break :blk definition_index < context.use_index;
}
break :blk false;
},
};
}