tiny.choir.ir.rewrite
Defined in ir.
API (96)
Actions
Public operations.
PatternIndex.activatePatternIndex.deinitPatternIndex.initPatternIndex.matchingPatternRewriteAttempt.finishPatternRewriteAttempt.initPatternRewriter.Listener.bindPatternRewriter.Listener.notifyPatternRewriter.applyPendingReplacementsPatternRewriter.clearInsertionPointPatternRewriter.createPatternRewriter.deinitPatternRewriter.destroyDetachedOperationsPatternRewriter.detachScheduledOperationsPatternRewriter.eraseOpPatternRewriter.finalizePatternRewriter.getListenerPatternRewriter.getRemappedValuePatternRewriter.getTypeConverterPatternRewriter.hasInsertionPointPatternRewriter.initPatternRewriter.initDeferredPatternRewriter.initWithTypeConverterPatternRewriter.insertPatternRewriter.insertionGuardPatternRewriter.isScheduledForErasePatternRewriter.materializeConversionPatternRewriter.replaceAllOpUsesWithPatternRewriter.replaceAllOpUsesWithOperationPatternRewriter.replaceAllUsesWithPatternRewriter.replaceOpPatternRewriter.replaceOpWithNewOpPatternRewriter.replaceOpWithOperationPatternRewriter.replaceOpWithValuePatternRewriter.restoreDetachedOperationsPatternRewriter.restoreInsertionPointPatternRewriter.rollbackCreatedOperationsPatternRewriter.saveInsertionPointPatternRewriter.setAttrPatternRewriter.setInsertionPointPatternRewriter.setInsertionPointAfterPatternRewriter.setInsertionPointBeforePatternRewriter.setListenerPatternRewriter.setOperandValuePatternRewriter.setTypeConverterRewritePattern.applyRewritePattern.initRewritePattern.initWithMatchRewritePattern.lessThanRewritePattern.matchAndRewriteRewritePattern.matchesRewritePattern.matchesAfterRootRewritePatternSet.addRewritePatternSet.addPatternRewritePatternSet.applyFirstMatchingPatternRewritePatternSet.countRewritePatternSet.deinitRewritePatternSet.ensureUnusedCapacityRewritePatternSet.getMatchingPatternsRewritePatternSet.initRewritePatternSet.sealTypeConverter.addConversionTypeConverter.convertTypeTypeConverter.convertTypesAllocTypeConverter.deinitTypeConverter.initTypeConverter.isTypeLegalTypeConverter.materializeTypeConverter.setMaterializationtryApplyRewritePattern
Types and contracts
Public types and contracts.
DialectCanonicalizationInterfacePatternBenefitPatternIndexPatternIndex.CapacityPatternIndex.LimitsPatternResultPatternRewriteAttemptPatternRewriterPatternRewriter.DetachedOperationPatternRewriter.InsertPointPatternRewriter.InsertionGuardPatternRewriter.ListenerPatternRewriter.OperationReplacementPatternRewriter.ReplacementModePatternRewriter.RewriteEventRewritePatternRewritePatternKindRewritePatternProductsRewritePatternSetRewritePatternSpecTypeConverterTypeConverter.MaterializeFnTypeConverter.TypeConversionResult
Values and defaults
Public values and defaults.
Source
Source: lib/choir/src/core/rewrite/index.zig:88
pub const PatternIndex = struct { pub const claim: alloc_phase.capacity.Declaration = .{ .source = .{ .id = "choir.rewrite_pattern_index", .kind = .phase_static, .limit_source = .caller, .storage = .{ .covered = &.{ .{ .id = "load_bounded_rewrite_root_slots_and_exact_sealed_pattern_groups", .lifetime = .steady, .detail = "load-bounded rewrite-root slots and exact sealed pattern groups", }, }, .excluded = &.{ "geometrically grown rewrite-pattern builder storage", "borrowed root names, rewrite callbacks, IR, and pattern-rewriter state", }, }, .capacity = .{ .inputs = &.{ alloc_phase.capacity.bindInput(Limits, "patterns", "patterns"), }, .type_selectors = &.{ alloc_phase.capacity.bindType(PatternRootSlot, "rootslot"), alloc_phase.capacity.bindType(RewritePattern, "rewritepattern"), }, .nodes = &.{ .{ .collection = .{ .length = 0 } }, .{ .constant = 2 }, .{ .scale = .{ .node = 1, .coefficient = .{ .size_of_concrete_type = 0 } } }, .{ .scale = .{ .node = 0, .coefficient = .{ .size_of_concrete_type = 1 } } }, .{ .add = .{ .left = 2, .right = 3 } }, }, .assertions = &.{.{ .scope = .closure_total, .measure = .retained, .relation = .exact, .expression = 4, }}, }, .overload = .{ .kind = .reject_before_seal, .detail = "pattern-count, unique-root count, placement arithmetic, or OOM failure leaves the pattern set unsealed and retryable", }, .risks = .{ .transitive = .{ .status = .open, .detail = "benefit sorting and root-name hashing use standard-library helpers without a transitive allocation-closure certificate", }, .foreign = .{ .status = .excluded, .detail = "pattern indexing is process-local and invokes no callback or operating-system boundary", }, }, .obligations = &.{ .{ .key = "pattern_index_capacity", .role = .capacity_model }, .{ .key = "pattern_index_sealed_reuse_overload", .role = .overload }, .{ .key = "pattern_index_sealed_reuse_transitive_risk", .role = .transitive_risk }, .{ .key = "pattern_index_sealed_reuse_foreign_risk", .role = .foreign_risk }, .{ .key = "pattern_index_oom_retry", .role = .overload }, }, }, .bindings = .{ .owner = @This(), .seal = .{ .family = alloc_phase.capacity.selector(@This().activate), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, .teardown = .{ .family = alloc_phase.capacity.selector(@This().deinit), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, }, }; phase: alloc_phase.capacity.Phase, capacity: PatternIndexCapacity, source_patterns: ?[]const RewritePattern, bytes: []align(pattern_index_alignment) u8, slots: []PatternRootSlot, grouped_patterns: []RewritePattern, root_count: usize, pub const Limits = PatternIndexLimits; pub const Capacity = PatternIndexCapacity; pub fn init(allocator: std.mem.Allocator, limits: PatternIndexLimits) !PatternIndex { const capacity = try PatternIndexCapacity.derive(limits); const bytes = try allocator.alignedAlloc( u8, .fromByteUnits(pattern_index_alignment), capacity.working_bytes, ); errdefer allocator.free(bytes); const slots = patternIndexSlice( PatternRootSlot, bytes, capacity.slots_offset, capacity.slot_count, ); @memset(slots, .{}); const grouped_patterns = patternIndexSlice( RewritePattern, bytes, capacity.patterns_offset, capacity.facts.pattern_count, ); var root_count: usize = 0; for (limits.patterns) |pattern| { const insertion = getOrInsertPatternRoot(slots, pattern.spec.root_op_name); root_count += @intFromBool(insertion.inserted); slots[insertion.index].len = std.math.add( PatternOrdinal, slots[insertion.index].len, 1, ) catch unreachable; } setPatternRootStarts(slots, grouped_patterns.len); var source_index = limits.patterns.len; while (source_index > 0) { source_index -= 1; const pattern = limits.patterns[source_index]; const slot_index = findPatternRootSlotIndex( slots, pattern.spec.root_op_name, ).?; std.debug.assert(slots[slot_index].len > 0); slots[slot_index].len -= 1; const grouped_index = @as(usize, slots[slot_index].start) + @as(usize, slots[slot_index].len); std.debug.assert(grouped_index < grouped_patterns.len); grouped_patterns[grouped_index] = pattern; } restorePatternRootLengths(slots, grouped_patterns.len); const index = PatternIndex{ .phase = .initialization, .capacity = capacity, .source_patterns = limits.patterns, .bytes = bytes, .slots = slots, .grouped_patterns = grouped_patterns, .root_count = root_count, }; index.assertInvariant(); return index; } pub fn activate(self: *PatternIndex) error{ AlreadyActive, InputChanged }!void { if (self.phase != .initialization) return error.AlreadyActive; if (self.source_patterns == null) return error.InputChanged; self.source_patterns = null; self.phase = .steady; self.assertInvariant(); } pub fn deinit(self: *PatternIndex, allocator: std.mem.Allocator) void { if (self.phase == .teardown) @panic("rewrite pattern index teardown is terminal"); self.assertInvariant(); self.phase = .teardown; allocator.free(self.bytes); self.source_patterns = undefined; self.bytes = undefined; self.slots = undefined; self.grouped_patterns = undefined; self.root_count = undefined; } pub fn matching(self: *const PatternIndex, root_name: []const u8) []const RewritePattern { self.requireSteady(); std.debug.assert(self.grouped_patterns.len == self.capacity.facts.pattern_count); std.debug.assert(self.slots.len == self.capacity.slot_count); const range = self.findRoot(root_name) orelse return &.{}; const start: usize = @intCast(range.start); const len: usize = @intCast(range.len); std.debug.assert(start <= self.grouped_patterns.len); std.debug.assert(len <= self.grouped_patterns.len - start); return self.grouped_patterns[start..][0..len]; } fn findRoot(self: *const PatternIndex, root_name: []const u8) ?PatternRootSlot { const slot_index = findPatternRootSlotIndex(self.slots, root_name) orelse return null; return self.slots[slot_index]; } fn requireSteady(self: *const PatternIndex) void { if (self.phase != .steady) @panic("rewrite pattern index is not active"); } fn assertInvariant(self: *const PatternIndex) void { std.debug.assert(self.phase != .teardown); std.debug.assert(self.bytes.len == self.capacity.working_bytes); if (self.phase == .initialization) { std.debug.assert(self.source_patterns != null); std.debug.assert(self.source_patterns.?.len == self.capacity.facts.pattern_count); } else { std.debug.assert(self.source_patterns == null); } std.debug.assert(self.slots.len == self.capacity.slot_count); std.debug.assert(self.grouped_patterns.len == self.capacity.facts.pattern_count); var root_count: usize = 0; var pattern_count: usize = 0; for (self.slots) |slot| { const name = slot.name orelse continue; root_count += 1; std.debug.assert(slot.len > 0); const start: usize = @intCast(slot.start); const len: usize = @intCast(slot.len); std.debug.assert(start <= self.grouped_patterns.len); std.debug.assert(len <= self.grouped_patterns.len - start); pattern_count = std.math.add(usize, pattern_count, len) catch unreachable; std.debug.assert(pattern_count <= self.grouped_patterns.len); const found = self.findRoot(name).?; std.debug.assert(found.start == slot.start); std.debug.assert(found.len == slot.len); } std.debug.assert(root_count == self.root_count); std.debug.assert(pattern_count == self.grouped_patterns.len); for (self.grouped_patterns, 0..) |_, pattern_index| { var containing_ranges: usize = 0; for (self.slots) |slot| { if (slot.name == null) continue; const start: usize = @intCast(slot.start); const len: usize = @intCast(slot.len); if (pattern_index >= start and pattern_index - start < len) { containing_ranges += 1; } } std.debug.assert(containing_ranges == 1); } } fn matchesPatterns(self: *const PatternIndex) bool { if (self.grouped_patterns.len != self.capacity.facts.pattern_count) return false; for (self.slots) |slot| { const root_name = slot.name orelse continue; const start: usize = @intCast(slot.start); const len: usize = @intCast(slot.len); for (self.grouped_patterns[start..][0..len], 0..) |pattern, group_index| { if (!std.mem.eql( u8, root_name, pattern.spec.root_op_name, )) return false; if (group_index > 0 and RewritePattern.lessThan( {}, pattern, self.grouped_patterns[start + group_index - 1], )) return false; } } return true; }};Source: lib/choir/src/core/rewrite/pattern.zig:92
pub const PatternResult = enum { success, failure,};Source: lib/choir/src/core/rewrite/pattern.zig:26
pub const RewritePattern = struct { spec: RewritePatternSpec, rewrite_fn: *const fn ( op: *ir.Operation, rewriter: *PatternRewriter, ) PatternResult, match_fn: ?*const fn (op: *ir.Operation) bool, order: usize, pub fn init( spec: RewritePatternSpec, rewrite_fn: *const fn (*ir.Operation, *PatternRewriter) PatternResult, ) RewritePattern { return .{ .spec = spec, .rewrite_fn = rewrite_fn, .match_fn = null, .order = 0, }; } pub fn initWithMatch( spec: RewritePatternSpec, match_fn: *const fn (*ir.Operation) bool, rewrite_fn: *const fn (*ir.Operation, *PatternRewriter) PatternResult, ) RewritePattern { return .{ .spec = spec, .rewrite_fn = rewrite_fn, .match_fn = match_fn, .order = 0, }; } pub fn matches(self: *const RewritePattern, op: *ir.Operation) bool { if (!std.mem.eql(u8, op.name.name, self.spec.root_op_name)) { return false; } return self.matchesAfterRoot(op); } pub fn matchesAfterRoot(self: *const RewritePattern, op: *ir.Operation) bool { if (self.match_fn) |match| { return match(op); } return true; } pub fn apply(self: *const RewritePattern, op: *ir.Operation, rewriter: *PatternRewriter) PatternResult { return self.rewrite_fn(op, rewriter); } pub fn matchAndRewrite(self: *const RewritePattern, op: *ir.Operation, rewriter: *PatternRewriter) PatternResult { if (!self.matches(op)) return .failure; return self.apply(op, rewriter); } pub fn lessThan(_: void, a: RewritePattern, b: RewritePattern) bool { if (a.spec.benefit != b.spec.benefit) return a.spec.benefit > b.spec.benefit; return a.order < b.order; }};Source: lib/choir/src/core/rewrite/pattern.zig:7
pub const RewritePatternKind = enum { rewrite, fold,};Source: lib/choir/src/core/rewrite/pattern.zig:12
pub const RewritePatternProducts = union(enum) { unknown, none, operations: []const []const u8,};Source: lib/choir/src/core/rewrite/pattern.zig:18
pub const RewritePatternSpec = struct { name: []const u8, root_op_name: []const u8, benefit: PatternBenefit = 1, kind: RewritePatternKind = .rewrite, products: RewritePatternProducts = .unknown,};Source: lib/choir/src/core/rewrite/rewriter.zig:8
pub const PatternRewriteAttempt = struct { rewriter: *PatternRewriter, created_before: usize, guard: PatternRewriter.InsertionGuard, pub inline fn init(op: *ir.Operation, rewriter: *PatternRewriter) PatternRewriteAttempt { const attempt = PatternRewriteAttempt{ .rewriter = rewriter, .created_before = rewriter.created_ops.items.len, .guard = rewriter.insertionGuard(), }; rewriter.setInsertionPointBefore(op); return attempt; } pub inline fn finish(self: *PatternRewriteAttempt, result: PatternResult) bool { if (result == .failure and self.rewriter.created_ops.items.len != self.created_before) { self.rewriter.created_ops.items.len = self.created_before; } self.guard.deinit(); self.* = undefined; return result == .success; }};Source: lib/choir/src/core/rewrite/rewriter.zig:52
pub const PatternRewriter = struct { pub const ReplacementMode = enum { immediate, deferred, }; allocator: std.mem.Allocator, ir_ctx: *ir.Context, type_converter: ?*const TypeConverter, replacement_mode: ReplacementMode, created_ops: std.ArrayListUnmanaged(*ir.Operation), ops_to_erase: std.ArrayListUnmanaged(*ir.Operation), replacements: std.AutoHashMap(*ir.Value, *ir.Value), builder: ir.OperationBuilder, listener: ?Listener, pub const InsertPoint: type = ir.OperationBuilder.InsertPoint; pub const InsertionGuard: type = ir.OperationBuilder.InsertionGuard; pub const OperationReplacement = struct { op: *ir.Operation, new_values: []const *ir.Value, }; pub const DetachedOperation = struct { op: *ir.Operation, block: *ir.Block, next: ?*ir.Operation, }; pub const RewriteEvent = union(enum) { modified: *ir.Operation, replaced: OperationReplacement, erased: *ir.Operation, }; pub const Listener = struct { context: ?*anyopaque = null, notify_event: ?*const fn (?*anyopaque, RewriteEvent) void = null, pub fn bind(target: anytype) Listener { const TargetPtr = @TypeOf(target); comptime { const pointer_info = switch (@typeInfo(TargetPtr)) { .pointer => |info| info, else => @compileError("PatternRewriter.Listener.bind expects a mutable pointer"), }; if (pointer_info.size != .one) { @compileError("PatternRewriter.Listener.bind expects a single-item pointer"); } if (pointer_info.attrs.@"const") { @compileError("PatternRewriter.Listener.bind expects a mutable pointer"); } if (!@hasDecl(pointer_info.child, "notifyRewriteEvent")) { @compileError("PatternRewriter listener target must define notifyRewriteEvent"); } } return .{ .context = target, .notify_event = rewrite_listener_target(TargetPtr).notify_event, }; } pub fn notify(self: Listener, event: RewriteEvent) void { if (self.notify_event) |notify_event| notify_event(self.context, event); } }; pub fn init(allocator: std.mem.Allocator, ir_ctx: *ir.Context) PatternRewriter { return initWithMode(allocator, ir_ctx, .immediate); } pub fn initDeferred(allocator: std.mem.Allocator, ir_ctx: *ir.Context) PatternRewriter { return initWithMode(allocator, ir_ctx, .deferred); } fn initWithMode( allocator: std.mem.Allocator, ir_ctx: *ir.Context, replacement_mode: ReplacementMode, ) PatternRewriter { return .{ .allocator = allocator, .ir_ctx = ir_ctx, .type_converter = null, .replacement_mode = replacement_mode, .created_ops = .empty, .ops_to_erase = .empty, .replacements = std.AutoHashMap(*ir.Value, *ir.Value).init(allocator), .builder = ir.OperationBuilder.init(ir_ctx), .listener = null, }; } pub fn initWithTypeConverter( allocator: std.mem.Allocator, ir_ctx: *ir.Context, type_converter: ?*const TypeConverter, ) PatternRewriter { var rewriter = PatternRewriter.init(allocator, ir_ctx); rewriter.type_converter = type_converter; return rewriter; } pub fn deinit(self: *PatternRewriter) void { self.created_ops.deinit(self.allocator); self.ops_to_erase.deinit(self.allocator); self.replacements.deinit(); } pub fn setTypeConverter(self: *PatternRewriter, type_converter: ?*const TypeConverter) void { self.type_converter = type_converter; } pub fn getTypeConverter(self: *const PatternRewriter) ?*const TypeConverter { return self.type_converter; } pub fn setListener(self: *PatternRewriter, listener: ?Listener) void { self.listener = listener; } pub fn getListener(self: *const PatternRewriter) ?Listener { return self.listener; } pub fn materializeConversion(self: *PatternRewriter, value: *ir.Value, target_type: ir.Type) ?*ir.Value { const converter = self.type_converter orelse return null; return converter.materialize(self, value, target_type); } pub fn clearInsertionPoint(self: *PatternRewriter) void { self.builder.clearInsertionPoint(); } pub fn hasInsertionPoint(self: *const PatternRewriter) bool { return self.builder.hasInsertionPoint(); } pub fn saveInsertionPoint(self: *const PatternRewriter) InsertPoint { return self.builder.saveInsertionPoint(); } pub fn restoreInsertionPoint(self: *PatternRewriter, insert_point: InsertPoint) void { self.builder.restoreInsertionPoint(insert_point); } pub fn insertionGuard(self: *PatternRewriter) InsertionGuard { return self.builder.insertionGuard(); } pub fn setInsertionPoint(self: *PatternRewriter, block: *ir.Block) void { self.builder.setInsertionPoint(block); } pub fn setInsertionPointBefore(self: *PatternRewriter, op: *ir.Operation) void { self.builder.setInsertionPointBefore(op); } pub fn setInsertionPointAfter(self: *PatternRewriter, op: *ir.Operation) void { self.builder.setInsertionPointAfter(op); } fn ensureBuilderListener(self: *PatternRewriter) void { self.builder.setListener(.{ .context = self, .notify_operation_inserted = recordInsertedOperation, }); } fn recordInsertedOperation(context: ?*anyopaque, op: *ir.Operation, previous: ir.OperationBuilder.InsertPoint) !void { _ = previous; const self: *PatternRewriter = @ptrCast(@alignCast(context.?)); try self.created_ops.append(self.allocator, op); } pub fn insert(self: *PatternRewriter, op: *ir.Operation) !*ir.Operation { self.ensureBuilderListener(); return try self.builder.insert(op); } pub fn create(self: *PatternRewriter, state: ir.Operation.State) !*ir.Operation { self.ensureBuilderListener(); return try self.builder.create(state); } fn notifyRewriteEvent(self: *const PatternRewriter, event: RewriteEvent) void { if (self.listener) |listener| listener.notify(event); } fn replaceUsesImmediately(self: *PatternRewriter, old_value: *ir.Value, new_value: *ir.Value) void { if (old_value == new_value) return; var uses = old_value.useIterator(); while (uses.next()) |operand| { operand.setValue(new_value); const owner: *ir.Operation = @ptrCast(@alignCast(operand.owner)); self.notifyRewriteEvent(.{ .modified = owner }); } } fn ensureReplacementCapacity(self: *PatternRewriter, count: usize) !void { if (self.replacement_mode == .deferred) { try self.replacements.ensureUnusedCapacity(@intCast(count)); } } fn ensureEraseCapacity(self: *PatternRewriter) !void { try self.ops_to_erase.ensureUnusedCapacity(self.allocator, 1); } pub fn setOperandValue(self: *PatternRewriter, op: *ir.Operation, index: usize, new_value: *ir.Value) void { op.setOperandValue(index, new_value); self.notifyRewriteEvent(.{ .modified = op }); } pub fn setAttr(self: *PatternRewriter, op: *ir.Operation, attr_name: []const u8, value: ir.Attribute) !void { try op.setAttr(attr_name, value); self.notifyRewriteEvent(.{ .modified = op }); } pub fn replaceAllUsesWith(self: *PatternRewriter, old_value: *ir.Value, new_value: *ir.Value) !void { switch (self.replacement_mode) { .immediate => self.replaceUsesImmediately(old_value, new_value), .deferred => try self.replacements.put(old_value, new_value), } } pub fn replaceAllOpUsesWith(self: *PatternRewriter, op: *ir.Operation, new_values: []const *ir.Value) !void { if (new_values.len != op.getNumResults()) return error.ReplacementResultCountMismatch; try self.ensureReplacementCapacity(new_values.len); self.notifyRewriteEvent(.{ .replaced = .{ .op = op, .new_values = new_values } }); switch (self.replacement_mode) { .immediate => for (op.results.items, new_values) |*result, new_value| { self.replaceUsesImmediately(result, new_value); }, .deferred => for (op.results.items, new_values) |*result, new_value| { self.replacements.putAssumeCapacity(result, new_value); }, } } pub fn replaceAllOpUsesWithOperation(self: *PatternRewriter, op: *ir.Operation, replacement: *ir.Operation) !void { const result_count = op.getNumResults(); if (replacement.getNumResults() != result_count) return error.ReplacementResultCountMismatch; if (result_count == 0) { try self.replaceAllOpUsesWith(op, &.{}); return; } if (result_count == 1) { const value = replacement.getResult(0) orelse return error.ReplacementResultCountMismatch; try self.replaceAllOpUsesWith(op, &.{value}); return; } const values = try self.allocator.alloc(*ir.Value, result_count); defer self.allocator.free(values); for (values, 0..) |*value, index| { value.* = replacement.getResult(index) orelse return error.ReplacementResultCountMismatch; } try self.replaceAllOpUsesWith(op, values); } pub fn replaceOp(self: *PatternRewriter, op: *ir.Operation, new_values: []const *ir.Value) !void { if (new_values.len != op.getNumResults()) return error.ReplacementResultCountMismatch; try self.ensureEraseCapacity(); try self.replaceAllOpUsesWith(op, new_values); self.ops_to_erase.appendAssumeCapacity(op); } pub fn replaceOpWithOperation(self: *PatternRewriter, op: *ir.Operation, replacement: *ir.Operation) !void { if (replacement.getNumResults() != op.getNumResults()) return error.ReplacementResultCountMismatch; try self.ensureEraseCapacity(); try self.replaceAllOpUsesWithOperation(op, replacement); self.ops_to_erase.appendAssumeCapacity(op); } pub fn replaceOpWithNewOp(self: *PatternRewriter, op: *ir.Operation, state: ir.Operation.State) !*ir.Operation { const result_count = op.getNumResults(); if (state.result_types.len != result_count) return error.ReplacementResultCountMismatch; try self.ensureEraseCapacity(); try self.ensureReplacementCapacity(result_count); const new_op = try self.create(state); try self.replaceOpWithOperation(op, new_op); return new_op; } pub fn replaceOpWithValue(self: *PatternRewriter, op: *ir.Operation, new_value: *ir.Value) !void { try self.replaceOp(op, &.{new_value}); } pub fn eraseOp(self: *PatternRewriter, op: *ir.Operation) !void { try self.ops_to_erase.append(self.allocator, op); } pub fn isScheduledForErase(self: *const PatternRewriter, op: *const ir.Operation) bool { for (self.ops_to_erase.items) |erased_op| { if (erased_op == op) return true; } return false; } pub fn getRemappedValue(self: *const PatternRewriter, value: *ir.Value) *ir.Value { if (self.replacement_mode == .immediate) return value; var current = value; while (self.replacements.get(current)) |replacement| { current = replacement; } return current; } pub fn finalize(self: *PatternRewriter, root_op: *ir.Operation) void { self.applyPendingReplacements(root_op); for (self.ops_to_erase.items) |op| { self.notifyRewriteEvent(.{ .erased = op }); op.erase(); } } pub fn applyPendingReplacements(self: *PatternRewriter, root_op: *ir.Operation) void { if (self.replacement_mode == .immediate) return; if (self.replacements.count() != 0) self.applyReplacementsToOp(root_op); } pub fn detachScheduledOperations( self: *PatternRewriter, storage: []DetachedOperation, ) []DetachedOperation { std.debug.assert(storage.len >= self.ops_to_erase.items.len); for (self.ops_to_erase.items, 0..) |op, index| { const block = op.getBlock() orelse @panic("scheduled erased operation is detached"); storage[index] = .{ .op = op, .block = block, .next = op.next_op, }; self.notifyRewriteEvent(.{ .erased = op }); block.detachOperation(op); } return storage[0..self.ops_to_erase.items.len]; } pub fn restoreDetachedOperations(detached: []const DetachedOperation) void { var index = detached.len; while (index > 0) { index -= 1; const entry = detached[index]; if (entry.next) |next| { entry.block.insertBefore(entry.op, next) catch unreachable; } else { entry.block.addOperation(entry.op) catch unreachable; } } } pub fn destroyDetachedOperations(detached: []const DetachedOperation) void { for (detached) |entry| entry.op.dropAllReferences(); var index = detached.len; while (index > 0) { index -= 1; detached[index].op.erase(); } } pub fn rollbackCreatedOperations(self: *PatternRewriter) void { var index = self.created_ops.items.len; while (index > 0) { index -= 1; self.created_ops.items[index].erase(); } self.created_ops.clearRetainingCapacity(); } fn applyReplacementsToOp(self: *PatternRewriter, op: *ir.Operation) void { var context = ReplacementWalk{ .rewriter = self }; _ = op.walk(.{ .order = .pre_order }, &context, ReplacementWalk.visit) catch unreachable; }};Source: lib/choir/src/core/rewrite/set.zig:12
pub const RewritePatternSet = struct { allocator: std.mem.Allocator, patterns: std.ArrayListUnmanaged(RewritePattern), index: ?PatternIndex, pub fn init(allocator: std.mem.Allocator) RewritePatternSet { return .{ .allocator = allocator, .patterns = .empty, .index = null, }; } pub fn deinit(self: *RewritePatternSet) void { if (self.index) |*index| index.deinit(self.allocator); self.patterns.deinit(self.allocator); self.* = undefined; } pub fn add(self: *RewritePatternSet, pattern: RewritePattern) !void { if (self.index != null) return error.PatternSetSealed; var ordered = pattern; ordered.order = self.patterns.items.len; try self.patterns.append(self.allocator, ordered); } pub fn ensureUnusedCapacity(self: *RewritePatternSet, additional_count: usize) !void { if (self.index != null) return error.PatternSetSealed; const required_count = std.math.add( usize, self.patterns.items.len, additional_count, ) catch return error.CapacityOverflow; try self.patterns.ensureTotalCapacity(self.allocator, required_count); } pub fn addPattern( self: *RewritePatternSet, op_name: []const u8, rewrite_fn: *const fn (*ir.Operation, *PatternRewriter) PatternResult, ) !void { try self.add(RewritePattern.init(.{ .name = op_name, .root_op_name = op_name, }, rewrite_fn)); } pub fn count(self: *const RewritePatternSet) usize { if (self.index) |index| return index.capacity.facts.pattern_count; return self.patterns.items.len; } pub fn seal(self: *RewritePatternSet) !void { if (self.index != null) return; std.mem.sort(RewritePattern, self.patterns.items, {}, RewritePattern.lessThan); const limits = try PatternIndex.Limits.inspect(self.patterns.items); var index = try PatternIndex.init(self.allocator, limits); errdefer index.deinit(self.allocator); try index.activate(); self.patterns.deinit(self.allocator); self.patterns = .empty; self.index = index; } pub fn getMatchingPatterns(self: *const RewritePatternSet, op: *ir.Operation) []const RewritePattern { if (self.index) |*index| { return index.matching(op.name.name); } @panic("rewrite pattern set is not sealed"); } pub fn applyFirstMatchingPattern( self: *const RewritePatternSet, op: *ir.Operation, rewriter: *PatternRewriter, ) bool { for (self.getMatchingPatterns(op)) |*pattern| { if (tryApplyRewritePattern(pattern, op, rewriter)) return true; } return false; }};Source: lib/choir/src/core/rewrite/type.zig:5
pub const TypeConverter = struct { allocator: std.mem.Allocator, conversions: std.HashMap(TypeKey, TypeConversionResult, TypeKeyContext, std.hash_map.default_max_load_percentage), materialize_fn: ?MaterializeFn, const TypeKey = struct { name: []const u8, param_key: []const u8, }; const TypeKeyContext = struct { pub fn hash(_: TypeKeyContext, key: TypeKey) u64 { var hasher = std.hash.Wyhash.init(0); hasher.update(key.name); hasher.update(&[_]u8{0}); hasher.update(key.param_key); return hasher.final(); } pub fn eql(_: TypeKeyContext, a: TypeKey, b: TypeKey) bool { return std.mem.eql(u8, a.name, b.name) and std.mem.eql(u8, a.param_key, b.param_key); } }; pub const TypeConversionResult = struct { types: []ir.Type, }; pub const MaterializeFn = *const fn ( rewriter: *PatternRewriter, value: *ir.Value, target_type: ir.Type, ) ?*ir.Value; fn dupeTypes(allocator: std.mem.Allocator, target_types: []const ir.Type) ![]ir.Type { if (target_types.len == 0) { return try allocator.alloc(ir.Type, 0); } const duped = try allocator.alloc(ir.Type, target_types.len); @memcpy(duped, target_types); return duped; } pub fn init(allocator: std.mem.Allocator) TypeConverter { return .{ .allocator = allocator, .conversions = std.HashMap(TypeKey, TypeConversionResult, TypeKeyContext, std.hash_map.default_max_load_percentage).init(allocator), .materialize_fn = null, }; } pub fn deinit(self: *TypeConverter) void { var iter = self.conversions.iterator(); while (iter.next()) |entry| { const key = entry.key_ptr.*; self.allocator.free(key.name); if (key.param_key.len > 0) { self.allocator.free(key.param_key); } const types = entry.value_ptr.types; self.allocator.free(types); } self.conversions.deinit(); } pub fn addConversion(self: *TypeConverter, source_type: ir.Type, target_types: []const ir.Type) !void { const storage = source_type.getDialectStorage() orelse return error.InvalidType; const lookup_key = TypeKey{ .name = storage.name, .param_key = storage.param_key }; if (self.conversions.getPtr(lookup_key)) |result| { const types_copy = try dupeTypes(self.allocator, target_types); errdefer self.allocator.free(types_copy); self.allocator.free(result.types); result.types = types_copy; return; } const name_copy = try self.allocator.dupe(u8, storage.name); errdefer self.allocator.free(name_copy); const key_copy = if (storage.param_key.len > 0) try self.allocator.dupe(u8, storage.param_key) else ""; errdefer if (key_copy.len > 0) self.allocator.free(key_copy); const types_copy = try dupeTypes(self.allocator, target_types); errdefer self.allocator.free(types_copy); try self.conversions.put(.{ .name = name_copy, .param_key = key_copy }, TypeConversionResult{ .types = types_copy }); } pub fn setMaterialization(self: *TypeConverter, materialize_fn: MaterializeFn) void { self.materialize_fn = materialize_fn; } pub fn materialize(self: *const TypeConverter, rewriter: *PatternRewriter, value: *ir.Value, target_type: ir.Type) ?*ir.Value { const func = self.materialize_fn orelse return null; return func(rewriter, value, target_type); } pub fn convertType(self: *const TypeConverter, source_type: ir.Type) ?[]const ir.Type { if (source_type.getDialectStorage()) |storage| { const key = TypeKey{ .name = storage.name, .param_key = storage.param_key }; if (self.conversions.get(key)) |result| { return result.types; } } return null; } pub fn convertTypesAlloc(self: *const TypeConverter, allocator: std.mem.Allocator, source_types: []const ir.Type) ![]ir.Type { var out: std.ArrayListUnmanaged(ir.Type) = .empty; errdefer out.deinit(allocator); for (source_types) |source_type| { if (self.convertType(source_type)) |converted| { try out.appendSlice(allocator, converted); } else { try out.append(allocator, source_type); } } return out.toOwnedSlice(allocator); } pub fn isTypeLegal(self: *const TypeConverter, t: ir.Type) bool { return self.convertType(t) == null; }};Source: lib/choir/src/core/rewrite/canonicalization.zig:5
pub const builtin_pattern_benefit: rewrite.PatternBenefit = 10;Source: lib/choir/src/core/rewrite/canonicalization.zig:6
pub const fold_pattern_benefit: rewrite.PatternBenefit = 100;Source: lib/choir/src/core/rewrite/pattern.zig:5
pub const PatternBenefit = u16;Source: lib/choir/src/core/rewrite/rewriter.zig:33
pub inline fn tryApplyRewritePattern( pattern: *const RewritePattern, op: *ir.Operation, rewriter: *PatternRewriter,) bool { if (!pattern.matchesAfterRoot(op)) return false; var attempt = PatternRewriteAttempt.init(op, rewriter); return attempt.finish(pattern.apply(op, rewriter));}Source: lib/choir/src/core/rewrite/root.zig
const pattern_mod = @import("pattern.zig");pub const PatternBenefit = pattern_mod.PatternBenefit;pub const RewritePatternKind = pattern_mod.RewritePatternKind;pub const RewritePatternProducts = pattern_mod.RewritePatternProducts;pub const RewritePatternSpec = pattern_mod.RewritePatternSpec;pub const RewritePattern = pattern_mod.RewritePattern;pub const PatternResult = pattern_mod.PatternResult;const rewriter_mod = @import("rewriter.zig");pub const PatternRewriter = rewriter_mod.PatternRewriter;pub const PatternRewriteAttempt = rewriter_mod.PatternRewriteAttempt;pub const tryApplyRewritePattern = rewriter_mod.tryApplyRewritePattern;const set_mod = @import("set.zig");pub const RewritePatternSet = set_mod.RewritePatternSet;const index_mod = @import("index.zig");pub const PatternIndex = index_mod.PatternIndex;const type_mod = @import("type.zig");pub const TypeConverter = type_mod.TypeConverter;const canonicalization_mod = @import("canonicalization.zig");pub const DialectCanonicalizationInterface = canonicalization_mod.DialectCanonicalizationInterface;pub const builtin_pattern_benefit = canonicalization_mod.builtin_pattern_benefit;pub const fold_pattern_benefit = canonicalization_mod.fold_pattern_benefit;Source: lib/choir/src/core/root.zig:90
pub const rewrite = @import("rewrite/root.zig");Also reachable as
backends.wasm.emission.module_encoding.common.ir.rewrite.
Complete caller list for ir.rewrite.RewritePattern.init
11 direct callers.
lib.choir.src.backends.gpu.nvptx.conversion.runGpuToNvptx[function] — private source atlib/choir/src/backends/gpu/nvptx/conversion.zig:146in nearest public ownertiny.choir.backends.gpu.nvptx.conversionlib.choir.src.backends.gpu.spirv.conversion.runGpuToSpirv[function] — private source atlib/choir/src/backends/gpu/spirv/conversion.zig:134in nearest public ownertiny.choir.backends.gpu.spirv.conversionlib.choir.src.core.rewrite.checkRewritePatternIndexInitFailures[function] — private source atlib/choir/src/core/rewrite/index.zig:465in nearest public ownerlib.choir.src.core.rewritelib.choir.src.core.rewrite.pattern.test_RewritePattern_stores_inspectable_declaration[function] — test source atlib/choir/src/core/rewrite/pattern.zig:97in nearest public ownerlib.choir.src.core.rewrite.patterntiny.choir.ir.rewrite.RewritePatternSet.addPattern[method] atlib/choir/src/core/rewrite/set.zig:48lib.choir.src.core.rewrite.set.test_RewritePatternSet_indexes_matching_patterns_by_root_operation[function] — test source atlib/choir/src/core/rewrite/set.zig:172in nearest public ownerlib.choir.src.core.rewrite.setlib.choir.src.core.rewrite.set.test_RewritePatternSet_seal_preserves_equal-benefit_insertion_order_per_root[function] — test source atlib/choir/src/core/rewrite/set.zig:148in nearest public ownerlib.choir.src.core.rewrite.setlib.choir.src.core.rewrite.set.test_rewrite_pattern_builder_reuses_reserved_capacity[function] — test source atlib/choir/src/core/rewrite/set.zig:95in nearest public ownerlib.choir.src.core.rewrite.setlib.choir.src.core.rewrite.set.test_rewrite_pattern_set[function] — test source atlib/choir/src/core/rewrite/set.zig:207in nearest public ownerlib.choir.src.core.rewrite.setlib.choir.src.core.rewrite.test_rewrite_pattern_index_derives_exact_slot_and_pattern_capacity[function] — test source atlib/choir/src/core/rewrite/index.zig:488in nearest public ownerlib.choir.src.core.rewritelib.choir.src.core.rewrite.test_rewrite_pattern_index_reuses_exact_backing_after_sealing[function] — test source atlib/choir/src/core/rewrite/index.zig:571in nearest public ownerlib.choir.src.core.rewrite
Complete caller list for ir.rewrite.PatternRewriter.deinit
15 direct callers.
lib.choir.src.core.rewrite.rewriter.test_PatternRewriter_delegates_insertion_guard_to_operation_builder[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:499in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_finalize_remaps_nested_operands_through_operation_walk[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:933in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_immediate_replacement_uses_no_allocator_or_finalize_walk[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:618in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_listener_binds_typed_rewrite_events[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:565in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_listener_records_replacement_modification_and_erase[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:674in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_replaceOpWithNewOp_rejects_result_count_mismatches_before_insertion[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:898in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_replaceOpWithNewOp_remaps_replacement_results[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:845in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_replaceOpWithOperation_remaps_existing_operation_results[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:738in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_replaceOp_rejects_result_count_mismatches[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:594in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_tracks_inserted_ops_through_builder_listener[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:532in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.passes.optimizations.checkSharedExtractionWitness[function] — private source atlib/choir/src/passes/optimizations.zig:2635in nearest public ownertiny.choir.passes.optimizationslib.choir.src.passes.optimizations.runConstantFolding[function] — private source atlib/choir/src/passes/optimizations.zig:267in nearest public ownertiny.choir.passes.optimizationslib.choir.src.passes.optimizations.runDeadStoreElimination[function] — private source atlib/choir/src/passes/optimizations.zig:586in nearest public ownertiny.choir.passes.optimizationslib.choir.src.passes.optimizations.runLoadStoreForwarding[function] — private source atlib/choir/src/passes/optimizations.zig:472in nearest public ownertiny.choir.passes.optimizationslib.choir.src.passes.optimizations.runSparseConditionalConstantPropagation[function] — private source atlib/choir/src/passes/optimizations.zig:312in nearest public ownertiny.choir.passes.optimizations
Complete caller list for ir.rewrite.PatternRewriter.finalize
9 direct callers.
lib.choir.src.core.rewrite.rewriter.test_PatternRewriter_finalize_remaps_nested_operands_through_operation_walk[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:933in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_immediate_replacement_uses_no_allocator_or_finalize_walk[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:618in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_listener_records_replacement_modification_and_erase[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:674in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_replaceOpWithNewOp_remaps_replacement_results[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:845in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_replaceOpWithOperation_remaps_existing_operation_results[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:738in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.passes.optimizations.runConstantFolding[function] — private source atlib/choir/src/passes/optimizations.zig:267in nearest public ownertiny.choir.passes.optimizationslib.choir.src.passes.optimizations.runDeadStoreElimination[function] — private source atlib/choir/src/passes/optimizations.zig:586in nearest public ownertiny.choir.passes.optimizationslib.choir.src.passes.optimizations.runLoadStoreForwarding[function] — private source atlib/choir/src/passes/optimizations.zig:472in nearest public ownertiny.choir.passes.optimizationslib.choir.src.passes.optimizations.runSparseConditionalConstantPropagation[function] — private source atlib/choir/src/passes/optimizations.zig:312in nearest public ownertiny.choir.passes.optimizations
Complete caller list for ir.rewrite.PatternRewriter.init
16 direct callers.
tiny.choir.ir.rewrite.PatternRewriter.initWithTypeConverter[function] atlib/choir/src/core/rewrite/rewriter.zig:152lib.choir.src.core.rewrite.rewriter.test_PatternRewriter_delegates_insertion_guard_to_operation_builder[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:499in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_finalize_remaps_nested_operands_through_operation_walk[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:933in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_immediate_replacement_uses_no_allocator_or_finalize_walk[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:618in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_listener_binds_typed_rewrite_events[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:565in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_listener_records_replacement_modification_and_erase[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:674in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_replaceOpWithNewOp_rejects_result_count_mismatches_before_insertion[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:898in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_replaceOpWithNewOp_remaps_replacement_results[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:845in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_replaceOpWithOperation_remaps_existing_operation_results[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:738in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_replaceOp_rejects_result_count_mismatches[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:594in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.core.rewrite.rewriter.test_PatternRewriter_tracks_inserted_ops_through_builder_listener[function] — test source atlib/choir/src/core/rewrite/rewriter.zig:532in nearest public ownerlib.choir.src.core.rewrite.rewriterlib.choir.src.passes.optimizations.checkSharedExtractionWitness[function] — private source atlib/choir/src/passes/optimizations.zig:2635in nearest public ownertiny.choir.passes.optimizationslib.choir.src.passes.optimizations.runConstantFolding[function] — private source atlib/choir/src/passes/optimizations.zig:267in nearest public ownertiny.choir.passes.optimizationslib.choir.src.passes.optimizations.runDeadStoreElimination[function] — private source atlib/choir/src/passes/optimizations.zig:586in nearest public ownertiny.choir.passes.optimizationslib.choir.src.passes.optimizations.runLoadStoreForwarding[function] — private source atlib/choir/src/passes/optimizations.zig:472in nearest public ownertiny.choir.passes.optimizationslib.choir.src.passes.optimizations.runSparseConditionalConstantPropagation[function] — private source atlib/choir/src/passes/optimizations.zig:312in nearest public ownertiny.choir.passes.optimizations
Complete caller list for ir.rewrite.RewritePatternSet.add
7 direct callers.
lib.choir.src.backends.gpu.nvptx.conversion.runGpuToNvptx[function] — private source atlib/choir/src/backends/gpu/nvptx/conversion.zig:146in nearest public ownertiny.choir.backends.gpu.nvptx.conversionlib.choir.src.backends.gpu.spirv.conversion.runGpuToSpirv[function] — private source atlib/choir/src/backends/gpu/spirv/conversion.zig:134in nearest public ownertiny.choir.backends.gpu.spirv.conversionlib.choir.src.core.rewrite.checkRewritePatternIndexInitFailures[function] — private source atlib/choir/src/core/rewrite/index.zig:465in nearest public ownerlib.choir.src.core.rewritetiny.choir.ir.rewrite.RewritePatternSet.addPattern[method] atlib/choir/src/core/rewrite/set.zig:48lib.choir.src.core.rewrite.set.test_RewritePatternSet_indexes_matching_patterns_by_root_operation[function] — test source atlib/choir/src/core/rewrite/set.zig:172in nearest public ownerlib.choir.src.core.rewrite.setlib.choir.src.core.rewrite.set.test_RewritePatternSet_seal_preserves_equal-benefit_insertion_order_per_root[function] — test source atlib/choir/src/core/rewrite/set.zig:148in nearest public ownerlib.choir.src.core.rewrite.setlib.choir.src.core.rewrite.set.test_rewrite_pattern_set[function] — test source atlib/choir/src/core/rewrite/set.zig:207in nearest public ownerlib.choir.src.core.rewrite.set
Complete caller list for ir.rewrite.RewritePatternSet.init
8 direct callers.
lib.choir.src.backends.gpu.nvptx.conversion.runGpuToNvptx[function] — private source atlib/choir/src/backends/gpu/nvptx/conversion.zig:146in nearest public ownertiny.choir.backends.gpu.nvptx.conversionlib.choir.src.backends.gpu.spirv.conversion.runGpuToSpirv[function] — private source atlib/choir/src/backends/gpu/spirv/conversion.zig:134in nearest public ownertiny.choir.backends.gpu.spirv.conversionlib.choir.src.core.rewrite.checkRewritePatternIndexInitFailures[function] — private source atlib/choir/src/core/rewrite/index.zig:465in nearest public ownerlib.choir.src.core.rewritelib.choir.src.core.rewrite.set.test_RewritePatternSet_indexes_matching_patterns_by_root_operation[function] — test source atlib/choir/src/core/rewrite/set.zig:172in nearest public ownerlib.choir.src.core.rewrite.setlib.choir.src.core.rewrite.set.test_RewritePatternSet_seal_preserves_equal-benefit_insertion_order_per_root[function] — test source atlib/choir/src/core/rewrite/set.zig:148in nearest public ownerlib.choir.src.core.rewrite.setlib.choir.src.core.rewrite.set.test_rewrite_pattern_builder_reuses_reserved_capacity[function] — test source atlib/choir/src/core/rewrite/set.zig:95in nearest public ownerlib.choir.src.core.rewrite.setlib.choir.src.core.rewrite.set.test_rewrite_pattern_set[function] — test source atlib/choir/src/core/rewrite/set.zig:207in nearest public ownerlib.choir.src.core.rewrite.setlib.choir.src.core.rewrite.test_rewrite_pattern_index_reuses_exact_backing_after_sealing[function] — test source atlib/choir/src/core/rewrite/index.zig:571in nearest public ownerlib.choir.src.core.rewrite
Audit
| Definitions | 96 |
|---|---|
| Public names | 192 |
| Members | 54 |
| Version | 26.7.0 |
| Revision | daab053ee433 |