Repository navigation
Relax bodies of functions when their signature can't be changed #9380
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
base: main
Are you sure you want to change the base?
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 |
|---|---|---|
|
|
@@ -213,26 +213,65 @@ | |
| ;; CHECK: (export "exported-not-relaxed" (func $exported-not-relaxed)) | ||
|
|
||
| ;; CHECK: (func $exported-not-relaxed (type $shared-sig) (param $ref (ref any)) (result (ref any)) | ||
| ;; CHECK-NEXT: (local.get $ref) | ||
| ;; CHECK-NEXT: (local $l anyref) | ||
| ;; CHECK-NEXT: (ref.as_non_null | ||
| ;; CHECK-NEXT: (block (result anyref) | ||
| ;; CHECK-NEXT: (local.set $l | ||
| ;; CHECK-NEXT: (local.get $ref) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: (drop | ||
| ;; CHECK-NEXT: (local.tee $l | ||
| ;; CHECK-NEXT: (local.get $ref) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: (local.get $l) | ||
| ;; CHECK-NEXT: ) | ||
|
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. [HIGH | Confidence: 5/5 | BUG] The lit test assertions for Because |
||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| (func $exported-not-relaxed (export "exported-not-relaxed") (param $ref (ref any)) (result (ref any)) | ||
| (local.get $ref) | ||
| ;; Function is exported, so we can't mutate its signature. Relax its locals | ||
| ;; but not its params. | ||
| (local $l (ref any)) | ||
| (local.set $l (local.get $ref)) | ||
| (drop (local.tee $l (local.get $ref))) | ||
| (local.get $l) | ||
| ) | ||
|
|
||
| ;; CHECK: (func $referenced-not-relaxed (type $shared-sig) (param $ref (ref any)) (result (ref any)) | ||
| ;; CHECK-NEXT: (local.get $ref) | ||
| ;; CHECK-NEXT: (local $l anyref) | ||
| ;; CHECK-NEXT: (ref.as_non_null | ||
| ;; CHECK-NEXT: (block (result anyref) | ||
| ;; CHECK-NEXT: (local.set $l | ||
| ;; CHECK-NEXT: (local.get $ref) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: (local.get $l) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| (func $referenced-not-relaxed (type $shared-sig) (param $ref (ref any)) (result (ref any)) | ||
| ;; Function referenced via ref.func: cannot be relaxed | ||
| (local.get $ref) | ||
| ;; Function referenced via ref.func. Relax its locals but not its params. | ||
| (local $l (ref any)) | ||
| (local.set $l (local.get $ref)) | ||
| (local.get $l) | ||
| ) | ||
|
|
||
| ;; CHECK: (func $referenced-via-table-not-relaxed (type $shared-sig) (param $ref (ref any)) (result (ref any)) | ||
| ;; CHECK-NEXT: (local.get $ref) | ||
| ;; CHECK-NEXT: (local $l anyref) | ||
| ;; CHECK-NEXT: (ref.as_non_null | ||
| ;; CHECK-NEXT: (block (result anyref) | ||
| ;; CHECK-NEXT: (local.set $l | ||
| ;; CHECK-NEXT: (local.get $ref) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: (local.get $l) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| (func $referenced-via-table-not-relaxed (type $shared-sig) (param $ref (ref any)) (result (ref any)) | ||
| ;; Function referenced via elem declare: cannot be relaxed | ||
| (local.get $ref) | ||
| ;; Function referenced via elem declare. Relax its locals but not its | ||
| ;; params. | ||
| (local $l (ref any)) | ||
| (local.set $l (local.get $ref)) | ||
| (local.get $l) | ||
| ) | ||
|
|
||
| (elem (i32.const 0) $referenced-via-table-not-relaxed) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[MEDIUM | Confidence: 5/5 | PERFORMANCE]
Checking
func->vars.size() > 0causesrunsOnFunctionto returntruefor every unrelaxable function (e.g. exported or referenced functions) that declares any local variables, even if all declared locals are primitive types (i32,i64,f32,f64) or already nullable.For these functions,
PassRunnerinstantiates the pass and performs a full AST traversal inSuper::doWalkFunction(func). BecausesignatureWasUpdatedisfalseand none offunc->varsare non-nullable references,makeNullabledoes nothing andchangedremainsfalse, making the entire AST walk a redundant no-op.To avoid traversing functions with only primitive or nullable locals, check whether any variable in
func->varsis a non-nullable reference: