Skip to content

[NFC] Speed up Unsubtyping #7734

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

[NFC] Speed up Unsubtyping #7734

wants to merge 3 commits into from

Conversation

tlively
Copy link
Member

@tlively tlively commented Jul 18, 2025

Speed up Unsubtyping by over 2x via algorithmic and other improvements.

The most expensive part of the Unsubtyping analysis is the handling of
casts. For each cast source and destination pair, each type that remains
a subtype of the source and was originally a subtype of the destination
must remain a subtype of the destination for the cast to continue
succeeding.

Previously, Unsubtyping analyzed these cast relationships for all types
as a single unit of work whenever it reached a fixed point from
examining other sources of subtyping constraints. This led to duplicated
work because the subtype, cast source, and cast destination triples
analyzed once would be analyzed again the next time casts were
considered.

Avoid this duplicated cast analysis by incrementally analyzing casts
whenever a new subtyping is discovered. Maintain the invariant that each
new subtyping either joins a subtyping tree rooted at the discovered
subtype into the discovered supertype's tree, or reparents the subtype
below some (possibly indirect) subtype of its old parent. In the former
case, the subtype and all of its descendents are evaluated against all
casts originating from all their new supertypes in the tree they have
joined. In the latter case, they must already have been evaluated
against all casts originating at the old supertype and its ancestors, so
they need only to be evaluated against their new supertypes up to the
old supertype. Once a particular type is evaluated against casts
originating from a particular supertype, that type will never be
evaluated against those casts again.

This algorithmic improvement accounts for most of the speedup. The rest
of the speedup is from doing less work while collecting the initial
subtyping constraints in a parallel function analysis. The old
implementation used an instance of Unsubtyping to collect constraints in
each function, which would end up doing some analysis to find additional
constraints. The new implementation does not do any analysis of
transitively required constraints during the initial parallel function
analysis.

@tlively tlively requested a review from kripken July 18, 2025 00:51
Speed up Unsubtyping by over 2x via algorithmic and other improvements.

The most expensive part of the Unsubtyping analysis is the handling of
casts. For each cast source and destination pair, each type that remains
a subtype of the source and was originally a subtype of the destination
must remain a subtype of the destination for the cast to continue
succeeding.

Previously, Unsubtyping analyzed these cast relationships for all types
as a single unit of work whenever it reached a fixed point from
examining other sources of subtyping constraints. This led to duplicated
work because the subtype, cast source, and cast destination triples
analyzed once would be analyzed again the next time casts were
considered.

Avoid this duplicated cast analysis by incrementally analyzing casts
whenever a new subtyping is discovered. Maintain the invariant that each
new subtyping either joins a subtyping tree rooted at the discovered
subtype into the discovered supertype's tree, or reparents the subtype
below some (possibly indirect) subtype of its old parent. In the former
case, the subtype and all of its descendents are evaluated against all
casts originating from all their new supertypes in the tree they have
joined. In the latter case, they must already have been evaluated
against all casts originating at the old supertype and its ancestors, so
they need only to be evaluated against their new supertypes up to the
old supertype. Once a particular type is evaluated against casts
originating from a particular supertype, that type will never be
evaluated against those casts again.

This algorithmic improvement accounts for most of the speedup. The rest
of the speedup is from doing less work while collecting the initial
subtyping constraints in a parallel function analysis. The old
implementation used an instance of Unsubtyping to collect constraints in
each function, which would end up doing some analysis to find additional
constraints. The new implementation does not do any analysis of
transitively required constraints during the initial parallel function
analysis.
@tlively tlively force-pushed the unsubtyping-rewrite branch from 2ff8dd1 to 038bb62 Compare July 18, 2025 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant