diff options
-rw-r--r-- | src/tools/wasm-reduce.cpp | 21 | ||||
-rw-r--r-- | test/reduce/gc.wast | 28 | ||||
-rw-r--r-- | test/reduce/gc.wast.txt | 16 |
3 files changed, 64 insertions, 1 deletions
diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 3b9229462..6613c8899 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -304,7 +304,7 @@ struct Reducer "--simplify-globals", "--simplify-locals --vacuum", "--strip", - "--remove-unused-types", + "--remove-unused-types --closed-world", "--vacuum"}; auto oldSize = file_size(working); bool more = true; @@ -627,6 +627,25 @@ struct Reducer // children (which would recreate the current state). return; } + } else if (auto* structNew = curr->dynCast<StructNew>()) { + // If all the fields are defaultable, try to replace this with a + // struct.new_with_default. + if (!structNew->isWithDefault() && structNew->type != Type::unreachable) { + auto& fields = structNew->type.getHeapType().getStruct().fields; + if (std::all_of(fields.begin(), fields.end(), [&](auto& field) { + return field.type.isDefaultable(); + })) { + ExpressionList operands(getModule()->allocator); + operands.swap(structNew->operands); + assert(structNew->isWithDefault()); + if (tryToReplaceCurrent(structNew)) { + return; + } else { + structNew->operands.swap(operands); + assert(!structNew->isWithDefault()); + } + } + } } // Finally, try to replace with a child. for (auto* child : ChildIterator(curr)) { diff --git a/test/reduce/gc.wast b/test/reduce/gc.wast new file mode 100644 index 000000000..98d1cd075 --- /dev/null +++ b/test/reduce/gc.wast @@ -0,0 +1,28 @@ +(module + (rec + (type $A (struct (field (mut i32)) (field funcref))) + ;; This type can be optimized away. + (type $unused (struct)) + ) + + (global $A (ref null $A) (struct.new $A + ;; These particular values are not used, and can be removed, leaving the + ;; struct.new as struct.new_default. + (i32.const 0) + (ref.func $use-global) + )) + + (func $use-global (export "use-global") (result i32) + ;; This function stores 42 in the global struct, then reads and returns + ;; that. We don't manage to optimize away anything in this function, which + ;; only serves to keep alive the type and the global for the above testing. + (struct.set $A 0 + (global.get $A) + (i32.const 42) + ) + (struct.get $A 0 + (global.get $A) + ) + ) +) + diff --git a/test/reduce/gc.wast.txt b/test/reduce/gc.wast.txt new file mode 100644 index 000000000..3af5287ce --- /dev/null +++ b/test/reduce/gc.wast.txt @@ -0,0 +1,16 @@ +(module + (type $0 (struct (field (mut i32)) (field funcref))) + (type $1 (func (result i32))) + (global $global$0 (ref null $0) (struct.new_default $0)) + (export "use-global" (func $0)) + (func $0 (result i32) + (struct.set $0 0 + (global.get $global$0) + (i32.const 42) + ) + (struct.get $0 0 + (global.get $global$0) + ) + ) +) + |