Skip to content

Commit ba0c818

Browse files
authored
[CustomDescriptors] RemoveUnusedModuleElements: Fix StructNew optimization of descriptor (#7650)
We have very special optimizations for StructNew in that pass: we see if they have reads (struct.get) and remove them if not. That explicit handling of StructNew was not aware of the new descriptor field, and so it could error, removing things that were still needed.
1 parent ab14353 commit ba0c818

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

scripts/test/fuzzing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
'unsubtyping-stack-switching.wast',
113113
'vacuum-stack-switching.wast',
114114
# TODO: fuzzer support for custom descriptors
115+
'remove-unused-module-elements-refs-descriptors.wast',
115116
'custom-descriptors.wast',
116117
'br_on_cast_desc.wast',
117118
'ref.get_desc.wast',

src/passes/RemoveUnusedModuleElements.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,13 @@ struct Analyzer {
482482
}
483483

484484
auto* new_ = curr->cast<StructNew>();
485+
486+
// Use the descriptor right now, normally. (We only have special
487+
// optimization for struct.new operands, below.)
488+
if (new_->descriptor) {
489+
use(new_->descriptor);
490+
}
491+
485492
auto type = new_->type.getHeapType();
486493

487494
for (Index i = 0; i < new_->operands.size(); i++) {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
;; RUN: foreach %s %t wasm-opt --remove-unused-module-elements --closed-world -all -S -o - | filecheck %s
3+
4+
;; The global.get of $global is the descriptor, not a field of the struct.
5+
;; We should not try to optimize it away and error.
6+
(module
7+
(rec
8+
;; CHECK: (rec
9+
;; CHECK-NEXT: (type $B (sub (descriptor $A (struct))))
10+
(type $B (sub (descriptor $A (struct))))
11+
;; CHECK: (type $A (sub (describes $B (struct))))
12+
(type $A (sub (describes $B (struct))))
13+
)
14+
15+
;; CHECK: (type $2 (func))
16+
17+
;; CHECK: (global $global (ref (exact $A)) (struct.new_default $A))
18+
(global $global (ref (exact $A)) (struct.new $A))
19+
20+
;; CHECK: (export "export" (func $export))
21+
22+
;; CHECK: (func $export (type $2)
23+
;; CHECK-NEXT: (drop
24+
;; CHECK-NEXT: (struct.new_default $B
25+
;; CHECK-NEXT: (global.get $global)
26+
;; CHECK-NEXT: )
27+
;; CHECK-NEXT: )
28+
;; CHECK-NEXT: )
29+
(func $export (export "export")
30+
(drop
31+
(struct.new $B
32+
(global.get $global)
33+
)
34+
)
35+
)
36+
)
37+

0 commit comments

Comments
 (0)