Skip to content

[GSI] Track exact type globals separately - #9334

Merged
tlively merged 1 commit into
mainfrom
gsi-exact-types
Nov 2, 2026
Merged

tlively merged 1 commit into
mainfrom
gsi-exact-types

Conversation

@tlively

@tlively tlively commented Oct 31, 2026

Copy link
Copy Markdown
Member

In GlobalStructInference::analyzeClosedWorld, unoptimizable types and typeGlobals are propagated from subtypes up to all declared supertypes because a struct.get or ref.get_desc on a non-exact reference to $super might access an instance of any subtype $sub. However, FunctionOptimizer::optimize also looked up typeGlobals[heapType] when the reference operand had an exact type (ref null? (exact $super)), which can never hold an instance of a strict subtype $sub at runtime. When optimizing (ref.get_desc $super ref) on an exact reference of type (ref (exact $super)), including globals that initialize a strict subtype $sub caused getReadValue to produce descriptors of type (ref (exact $sub.desc)), which is not a subtype of (ref (exact $super.desc)), widening the select result type to non-exact (ref $super.desc) and failing validation.

Save exactTypeGlobals after erasing directly unoptimizable types and before propagating unoptimizability and globals from subtypes to supertypes, and consult exactTypeGlobals in FunctionOptimizer::optimize when ref->type.isExact().

In `GlobalStructInference::analyzeClosedWorld`, `unoptimizable` types and `typeGlobals` are propagated from subtypes up to all declared supertypes because a `struct.get` or `ref.get_desc` on a non-exact reference to `$super` might access an instance of any subtype `$sub`. However, `FunctionOptimizer::optimize` also looked up `typeGlobals[heapType]` when the reference operand had an exact type `(ref null? (exact $super))`, which can never hold an instance of a strict subtype `$sub` at runtime. When optimizing `(ref.get_desc $super ref)` on an exact reference of type `(ref (exact $super))`, including globals that initialize a strict subtype `$sub` caused `getReadValue` to produce descriptors of type `(ref (exact $sub.desc))`, which is not a subtype of `(ref (exact $super.desc))`, widening the `select` result type to non-exact `(ref $super.desc)` and failing validation.

Save `exactTypeGlobals` after erasing directly unoptimizable types and before propagating unoptimizability and globals from subtypes to supertypes, and consult `exactTypeGlobals` in `FunctionOptimizer::optimize` when `ref->type.isExact()`.
@tlively
tlively requested a review from a team as a code owner October 31, 2026 07:40
@tlively
tlively requested review from kripken and removed request for a team October 31, 2026 07:40

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces exactTypeGlobals to the GlobalStructInference pass to optimize reads of exact references, which cannot refer to strict subtypes. This allows exact references to be optimized even when their supertypes or subtypes are unoptimizable. The feedback suggests sorting the vectors in exactTypeGlobals lexicographically to ensure determinism and consistency in the optimization output.

for (auto type : unoptimizable) {
typeGlobals.erase(type);
}
exactTypeGlobals = typeGlobals;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To ensure determinism and consistency, the vectors in exactTypeGlobals should be sorted lexicographically, just like typeGlobals is sorted at the end of analyzeClosedWorld. Since exactTypeGlobals is not modified after this copy, sorting it here guarantees that the optimization output remains independent of the order of globals in the module.

Suggested change
exactTypeGlobals = typeGlobals;
exactTypeGlobals = typeGlobals;
for (auto& [type, globals] : exactTypeGlobals) {
std::sort(globals.begin(), globals.end());
}

;; CHECK: (global $sub (ref $super) (struct.new_default_desc $sub
;; CHECK-NEXT: (global.get $sub.unnested.desc)
;; CHECK-NEXT: ))
(global $sub (ref $super) (struct.new_default_desc $sub

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, this global has type super but instantiates sub. Do we have a test where a global has type sub?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, global $A in the first module in this file.

@kripken kripken left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm otherwise

@tlively
tlively merged commit 944ed73 into main Nov 2, 2026
17 checks passed
@tlively
tlively deleted the gsi-exact-types branch November 2, 2026 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants