Skip to content

isUsedOnce counts references against stale bindings during inlining #143

Description

@Unisay

Problem

The reference counts that isUsedOnce consults are computed from the original uberModuleBindings (captured by the closure), while the fold's accumulator already contains bindings with earlier substitutions applied. Exports are counted from the accumulated (fresh) versions, so the count mixes stale and fresh sources.

This cannot produce dangling references (substitution replaces all occurrences regardless of the count), but it can misjudge use-once: a large expression can get inlined into several sites (code bloat), or a legitimate inline can be skipped. idempotently partially self-corrects on later iterations, at the cost of extra passes.

Approach

Compute counts against the same view of the module that the substitutions target. This falls out naturally from the incremental-counting rework in #142.

Prerequisites / Relations

Inliner correctness bug, found during the 2026-07-02 backend audit. Distinct from but closely related to #142: the fix for this defect falls out of #142's incremental-counting rework. Independent in the dependency graph.

Verification / Measurement

Use-once is judged against the current (post-substitution) view of the module, not a stale snapshot: a binding genuinely referenced once is inlined, and one referenced at multiple sites is no longer duplicated into all of them due to a miscount.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: irIR / optimizer / DCE / inlinerbugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions