diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp index adc69d4cc6d..088348f1c03 100644 --- a/src/ir/module-splitting.cpp +++ b/src/ir/module-splitting.cpp @@ -850,9 +850,11 @@ void ModuleSplitter::shareImportableItems() { for (auto& memory : primary.memories) { auto usingSecondaries = getUsingSecondaries(memory->name, &UsedNames::memories); - bool usedInPrimary = primaryUsed.memories.contains(memory->name); + bool inPrimary = primaryUsed.memories.contains(memory->name); - if (!usedInPrimary && usingSecondaries.size() == 1) { + if (!inPrimary && usingSecondaries.empty()) { + memoriesToRemove.push_back(memory->name); + } else if (!inPrimary && usingSecondaries.size() == 1) { auto* secondary = usingSecondaries[0]; ModuleUtils::copyMemory(memory.get(), *secondary); memoriesToRemove.push_back(memory->name); @@ -873,9 +875,11 @@ void ModuleSplitter::shareImportableItems() { for (auto& table : primary.tables) { auto usingSecondaries = getUsingSecondaries(table->name, &UsedNames::tables); - bool usedInPrimary = primaryUsed.tables.contains(table->name); + bool inPrimary = primaryUsed.tables.contains(table->name); - if (!usedInPrimary && usingSecondaries.size() == 1) { + if (!inPrimary && usingSecondaries.empty()) { + tablesToRemove.push_back(table->name); + } else if (!inPrimary && usingSecondaries.size() == 1) { auto* secondary = usingSecondaries[0]; assert(!secondary->getTableOrNull(table->name)); ModuleUtils::copyTable(table.get(), *secondary); @@ -903,12 +907,6 @@ void ModuleSplitter::shareImportableItems() { bool inPrimary = primaryUsed.globals.contains(global->name); if (!inPrimary && usingSecondaries.empty()) { - // It's not used anywhere, so delete it. Unlike other unused module items - // (memories, tables, and tags) that can just sit in the primary module - // and later be DCE'ed by another pass, we should remove it here, because - // an unused global can contain an initializer that refers to another - // global that will be moved to a secondary module, like - // (global $unused i32 (global.get $a)) // $a is moved to a secondary globalsToRemove.push_back(global->name); } else if (!inPrimary && usingSecondaries.size() == 1) { auto* secondary = usingSecondaries[0]; @@ -930,9 +928,11 @@ void ModuleSplitter::shareImportableItems() { std::vector tagsToRemove; for (auto& tag : primary.tags) { auto usingSecondaries = getUsingSecondaries(tag->name, &UsedNames::tags); - bool usedInPrimary = primaryUsed.tags.contains(tag->name); + bool inPrimary = primaryUsed.tags.contains(tag->name); - if (!usedInPrimary && usingSecondaries.size() == 1) { + if (!inPrimary && usingSecondaries.empty()) { + tagsToRemove.push_back(tag->name); + } else if (!inPrimary && usingSecondaries.size() == 1) { auto* secondary = usingSecondaries[0]; ModuleUtils::copyTag(tag.get(), *secondary); tagsToRemove.push_back(tag->name); diff --git a/test/example/module-splitting.cpp b/test/example/module-splitting.cpp index e09316acbef..a44aefa12fc 100644 --- a/test/example/module-splitting.cpp +++ b/test/example/module-splitting.cpp @@ -78,19 +78,19 @@ int main() { // Global stuff do_test({}, R"( (module - (memory $mem 3 42 shared) - (table $tab 3 42 funcref) - (global $glob (mut i32) (i32.const 7)) - (tag $e (param i32)) + (memory $mem (export "mem") 3 42 shared) + (table $tab (export "tab") 3 42 funcref) + (global $glob (export "glob") (mut i32) (i32.const 7)) + (tag $e (export "e") (param i32)) ))"); // Imported global stuff do_test({}, R"( (module - (import "env" "mem" (memory $mem 3 42 shared)) - (import "env" "tab" (table $tab 3 42 funcref)) - (import "env" "glob" (global $glob (mut i32))) - (import "env" "e" (tag $e (param i32))) + (memory $mem (export "mem") (import "env" "mem") 3 42 shared) + (table $tab (export "tab") (import "env" "tab") 3 42 funcref) + (global $glob (export "glob") (import "env" "glob") (mut i32)) + (tag $e (export "e") (import "env" "e") (param i32)) ))"); // Exported global stuff diff --git a/test/example/module-splitting.txt b/test/example/module-splitting.txt index 5f03322b7fe..f65f607f397 100644 --- a/test/example/module-splitting.txt +++ b/test/example/module-splitting.txt @@ -17,14 +17,23 @@ Before: (memory $mem 3 42 shared) (table $tab 3 42 funcref) (tag $e (type $0) (param i32)) + (export "mem" (memory $mem)) + (export "tab" (table $tab)) + (export "glob" (global $glob)) + (export "e" (tag $e)) ) Keeping: After: (module (type $0 (func (param i32))) + (global $glob (mut i32) (i32.const 7)) (memory $mem 3 42 shared) (table $tab 3 42 funcref) (tag $e (type $0) (param i32)) + (export "mem" (memory $mem)) + (export "tab" (table $tab)) + (export "glob" (global $glob)) + (export "e" (tag $e)) ) Secondary: (module @@ -38,6 +47,10 @@ Before: (import "env" "tab" (table $tab 3 42 funcref)) (import "env" "glob" (global $glob (mut i32))) (import "env" "e" (tag $e (type $0) (param i32))) + (export "mem" (memory $mem)) + (export "tab" (table $tab)) + (export "glob" (global $glob)) + (export "e" (tag $e)) ) Keeping: After: @@ -45,7 +58,12 @@ After: (type $0 (func (param i32))) (import "env" "mem" (memory $mem 3 42 shared)) (import "env" "tab" (table $tab 3 42 funcref)) + (import "env" "glob" (global $glob (mut i32))) (import "env" "e" (tag $e (type $0) (param i32))) + (export "mem" (memory $mem)) + (export "tab" (table $tab)) + (export "glob" (global $glob)) + (export "e" (tag $e)) ) Secondary: (module diff --git a/test/lit/wasm-split/passive.wast b/test/lit/wasm-split/passive.wast index 0b0fbfa7790..21d167ebce0 100644 --- a/test/lit/wasm-split/passive.wast +++ b/test/lit/wasm-split/passive.wast @@ -23,6 +23,20 @@ ;; PRIMARY: (export "table" (table $1)) + ;; PRIMARY: (func $use_table (type $0) + ;; PRIMARY-NEXT: (call_indirect $table (type $0) + ;; PRIMARY-NEXT: (i32.const 0) + ;; PRIMARY-NEXT: ) + ;; PRIMARY-NEXT: (elem.drop $passive) + ;; PRIMARY-NEXT: ) + (func $use_table + ;; Use $table so that it will not be deleted + (call_indirect $table + (i32.const 0) + ) + (elem.drop $passive) + ) + ;; PRIMARY: (func $in-table (type $0) ;; PRIMARY-NEXT: ) (func $in-table @@ -40,7 +54,8 @@ ;; SECONDARY-NEXT: ) (func $second-in-table ;; This is in a passive segment, and it is in the secondary module, so we will - ;; handle it by adding a trampoline from the segment as a new function "$1". + ;; handle it by adding a trampoline from the segment as a new function + ;; "$trampoline_second-in-table". ) ) ;; PRIMARY: (func $trampoline_second-in-table (type $0) diff --git a/test/lit/wasm-split/ref.func.wast b/test/lit/wasm-split/ref.func.wast index 5cc261dc4cd..0d3932c827b 100644 --- a/test/lit/wasm-split/ref.func.wast +++ b/test/lit/wasm-split/ref.func.wast @@ -19,8 +19,7 @@ ;; PRIMARY: (global $glob2 (ref func) (ref.func $trampoline_second)) ;; PRIMARY: (table $table 1 1 funcref) - (table $table 1 1 funcref) - + (table $table (export "table_export") 1 1 funcref) (global $glob1 (ref func) (ref.func $prime)) (global $glob2 (ref func) (ref.func $second)) @@ -34,6 +33,8 @@ ;; PRIMARY: (elem declare func $prime $trampoline_second) + ;; PRIMARY: (export "table_export" (table $table)) + ;; PRIMARY: (export "prime" (func $prime)) ;; PRIMARY: (export "table" (table $1)) diff --git a/test/lit/wasm-split/remove-unused-elements.wast b/test/lit/wasm-split/remove-unused-elements.wast new file mode 100644 index 00000000000..8295da5bd33 --- /dev/null +++ b/test/lit/wasm-split/remove-unused-elements.wast @@ -0,0 +1,25 @@ +;; RUN: wasm-split %s -all -g -o1 %t.1.wasm -o2 %t.2.wasm --keep-funcs=keep +;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY +;; RUN: wasm-dis %t.2.wasm | filecheck %s --check-prefix SECONDARY + +(module + (memory $unused-memory 1 1) + (global $unused-global i32 (i32.const 20)) + (table $unused-table 1 1 funcref) + (tag $unused-tag (param i32)) + + (func $keep) + (func $split) +) + +;; PRIMARY: (module +;; PRIMARY-NEXT: (type $0 (func)) +;; PRIMARY-NEXT: (func $keep +;; PRIMARY-NEXT: ) +;; PRIMARY-NEXT: ) + +;; SECONDARY: (module +;; SECONDARY-NEXT: (type $0 (func)) +;; SECONDARY-NEXT: (func $split +;; SECONDARY-NEXT: ) +;; SECONDARY-NEXT: ) diff --git a/test/lit/wasm-split/table64-const-offset.wast b/test/lit/wasm-split/table64-const-offset.wast index cd396f6361f..2e1f4d5eaa1 100644 --- a/test/lit/wasm-split/table64-const-offset.wast +++ b/test/lit/wasm-split/table64-const-offset.wast @@ -22,8 +22,8 @@ ;; PRIMARY-NOREF-NEXT: (import "placeholder.deferred" "1" (func $placeholder_1 (param i32) (result i32))) ;; PRIMARY-NOREF-NEXT: (table $table i64 2 2 funcref) ;; PRIMARY-NOREF-NEXT: (elem $0 (i64.const 0) $foo $placeholder_1) +;; PRIMARY-NOREF-NEXT: (export "%table_export" (table $table)) ;; PRIMARY-NOREF-NEXT: (export "%foo" (func $foo)) -;; PRIMARY-NOREF-NEXT: (export "%table" (table $table)) ;; PRIMARY-NOREF-NEXT: (func $foo (param $0 i32) (result i32) ;; PRIMARY-NOREF-NEXT: (call_indirect (type $0) ;; PRIMARY-NOREF-NEXT: (i32.const 0) @@ -34,7 +34,7 @@ ;; SECONDARY-NOREF: (module ;; SECONDARY-NOREF-NEXT: (type $0 (func (param i32) (result i32))) -;; SECONDARY-NOREF-NEXT: (import "primary" "%table" (table $table i64 2 2 funcref)) +;; SECONDARY-NOREF-NEXT: (import "primary" "%table_export" (table $table i64 2 2 funcref)) ;; SECONDARY-NOREF-NEXT: (import "primary" "%foo" (func $foo (param i32) (result i32))) ;; SECONDARY-NOREF-NEXT: (elem $0 (i64.const 1) $bar) ;; SECONDARY-NOREF-NEXT: (func $bar (param $0 i32) (result i32) @@ -51,6 +51,7 @@ ;; PRIMARY-REF-NEXT: (table $1 1 funcref) ;; PRIMARY-REF-NEXT: (elem $0 (table $table) (i64.const 0) func $foo) ;; PRIMARY-REF-NEXT: (elem $1 (table $1) (i32.const 0) func $placeholder_0) +;; PRIMARY-REF-NEXT: (export "%table_export" (table $table)) ;; PRIMARY-REF-NEXT: (export "%foo" (func $foo)) ;; PRIMARY-REF-NEXT: (export "%table" (table $1)) ;; PRIMARY-REF-NEXT: (func $foo (param $0 i32) (result i32) @@ -75,6 +76,7 @@ (module (table $table i64 1 1 funcref) + (export "%table_export" (table $table)) (elem (i64.const 0) $foo) (func $foo (param i32) (result i32) (call $bar (i32.const 0)) diff --git a/test/lit/wasm-split/table64-global-offset.wast b/test/lit/wasm-split/table64-global-offset.wast index ebcc930903b..809062c3d24 100644 --- a/test/lit/wasm-split/table64-global-offset.wast +++ b/test/lit/wasm-split/table64-global-offset.wast @@ -23,8 +23,8 @@ ;; PRIMARY-NOREF-NEXT: (import "placeholder.deferred" "1" (func $placeholder_1 (param i32) (result i32))) ;; PRIMARY-NOREF-NEXT: (table $table i64 2 2 funcref) ;; PRIMARY-NOREF-NEXT: (elem $0 (global.get $g) $foo $placeholder_1) +;; PRIMARY-NOREF-NEXT: (export "%table_export" (table $table)) ;; PRIMARY-NOREF-NEXT: (export "%foo" (func $foo)) -;; PRIMARY-NOREF-NEXT: (export "%table" (table $table)) ;; PRIMARY-NOREF-NEXT: (export "%global" (global $g)) ;; PRIMARY-NOREF-NEXT: (func $foo (param $0 i32) (result i32) ;; PRIMARY-NOREF-NEXT: (call_indirect (type $0) @@ -39,7 +39,7 @@ ;; SECONDARY-NOREF: (module ;; SECONDARY-NOREF-NEXT: (type $0 (func (param i32) (result i32))) -;; SECONDARY-NOREF-NEXT: (import "primary" "%table" (table $table i64 2 2 funcref)) +;; SECONDARY-NOREF-NEXT: (import "primary" "%table_export" (table $table i64 2 2 funcref)) ;; SECONDARY-NOREF-NEXT: (import "primary" "%global" (global $g i64)) ;; SECONDARY-NOREF-NEXT: (import "primary" "%foo" (func $foo (param i32) (result i32))) ;; SECONDARY-NOREF-NEXT: (elem $0 (global.get $g) $foo $bar) @@ -58,6 +58,7 @@ ;; PRIMARY-REF-NEXT: (table $1 1 funcref) ;; PRIMARY-REF-NEXT: (elem $0 (table $table) (global.get $g) func $foo) ;; PRIMARY-REF-NEXT: (elem $1 (table $1) (i32.const 0) func $placeholder_0) +;; PRIMARY-REF-NEXT: (export "%table_export" (table $table)) ;; PRIMARY-REF-NEXT: (export "%foo" (func $foo)) ;; PRIMARY-REF-NEXT: (export "%table" (table $1)) ;; PRIMARY-REF-NEXT: (func $foo (param $0 i32) (result i32) @@ -83,6 +84,7 @@ (module (global $g (import "env" "g") i64) (table $table i64 1 1 funcref) + (export "%table_export" (table $table)) (elem (global.get $g) $foo) (func $foo (param i32) (result i32) (call $bar (i32.const 0)) diff --git a/test/lit/wasm-split/trampoline.wast b/test/lit/wasm-split/trampoline.wast index 8c1fb5d5167..2fad323dacb 100644 --- a/test/lit/wasm-split/trampoline.wast +++ b/test/lit/wasm-split/trampoline.wast @@ -9,7 +9,7 @@ ;; PRIMARY: (import "placeholder.deferred" "0" (func $placeholder_0 (param i32) (result i32))) ;; PRIMARY: (table $table 1 1 funcref) - (table $table 1 1 funcref) + (table $table (export "table_export") 1 1 funcref) (elem (i32.const 0) $bar) (export "bar" (func $bar)) ;; PRIMARY: (table $1 1 funcref) @@ -18,6 +18,8 @@ ;; PRIMARY: (elem $1 (table $1) (i32.const 0) func $placeholder_0) + ;; PRIMARY: (export "table_export" (table $table)) + ;; PRIMARY: (export "bar" (func $trampoline_bar)) ;; PRIMARY: (export "foo" (func $foo))