-
Notifications
You must be signed in to change notification settings - Fork 860
GlobalStructInference: Handle nested optimizable global.gets #8019
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -267,3 +267,61 @@ | |
| ) | ||
| ) | ||
|
|
||
| ;; Nested struct.gets that seem optimizable. | ||
| (module | ||
| (rec | ||
| ;; CHECK: (rec | ||
| ;; CHECK-NEXT: (type $func (func (result anyref))) | ||
| (type $func (func (result anyref))) | ||
| ;; CHECK: (type $outer (sub (struct (field (ref $inner))))) | ||
| (type $outer (sub (struct (field (ref $inner))))) | ||
| ;; CHECK: (type $inner (sub (struct (field (ref $func))))) | ||
| (type $inner (sub (struct (field (ref $func))))) | ||
| ) | ||
|
|
||
| ;; CHECK: (type $3 (func (result anyref))) | ||
|
|
||
| ;; CHECK: (global $global.unnested.0 (ref (exact $inner)) (struct.new $inner | ||
| ;; CHECK-NEXT: (ref.func $func) | ||
| ;; CHECK-NEXT: )) | ||
|
|
||
| ;; CHECK: (global $global (ref $outer) (struct.new $outer | ||
| ;; CHECK-NEXT: (global.get $global.unnested.0) | ||
| ;; CHECK-NEXT: )) | ||
| (global $global (ref $outer) (struct.new $outer | ||
| (struct.new $inner | ||
| (ref.func $func) | ||
| ) | ||
| )) | ||
|
|
||
| ;; CHECK: (func $func (type $func) (result anyref) | ||
| ;; CHECK-NEXT: (unreachable) | ||
| ;; CHECK-NEXT: ) | ||
| (func $func (type $func) (result anyref) | ||
| (unreachable) | ||
| ) | ||
|
|
||
| ;; CHECK: (func $caller (type $3) (result anyref) | ||
| ;; CHECK-NEXT: (call_ref $func | ||
| ;; CHECK-NEXT: (struct.get $inner 0 | ||
| ;; CHECK-NEXT: (global.get $global.unnested.0) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| (func $caller (result anyref) | ||
| (call_ref $func | ||
| ;; TODO: If we did two passes, we could optimize this one too. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why doesn't this get optimized via un-nesting as well?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would just take another pass. Maybe worth it as the TODO says. (We could do it in a single pass with more complexity, or if we traversed in the other direction, in theory...)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, we can only do one level of un-nesting per pass because we're function-parallel and therefore cannot actually install the un-nested globals before we move on to the parent? That seems worth fixing! There's no reason why the globals wouldn't have very deep initialization trees, and we don't want to have to run this pass many times to fully optimize them.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it does seem worth fixing. We could perhaps just take a lock around global creation.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or maintain a per-function set of un-nested globals (with deterministic names) to be de-duplicated at the module level afterward. |
||
| (struct.get $inner 0 | ||
| ;; These two can be optimized, if we un-nest the global. When doing so we | ||
| ;; turn these into a global.get, with a global name that does not exist yet | ||
| ;; (we only create that global later in the pass). We must not think it is | ||
| ;; a complete global.get and try to optimize with it when we reach the | ||
| ;; parent struct.get. | ||
| (struct.get $outer 0 | ||
| (global.get $global) | ||
| ) | ||
| ) | ||
| ) | ||
| ) | ||
| ) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.