diff options
-rw-r--r-- | src/ir/module-splitting.cpp | 2 | ||||
-rw-r--r-- | src/ir/module-splitting.h | 6 | ||||
-rw-r--r-- | src/tools/wasm-split/wasm-split.cpp | 11 | ||||
-rw-r--r-- | test/example/module-splitting.cpp | 13 | ||||
-rw-r--r-- | test/lit/wasm-split/multi-split.wast | 102 |
5 files changed, 65 insertions, 69 deletions
diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp index 777818689..caa996b30 100644 --- a/src/ir/module-splitting.cpp +++ b/src/ir/module-splitting.cpp @@ -442,7 +442,7 @@ ModuleSplitter::classifyFunctions(Module& primary, const Config& config) { // module since that would make them async when they may not have the JSPI // wrapper. Exported JSPI functions can still benefit from splitting though // since only the JSPI wrapper stub will remain in the primary module. - if (func->imported() || config.primaryFuncs.count(func->name) || + if (func->imported() || !config.secondaryFuncs.count(func->name) || (config.jspi && ExportUtils::isExported(primary, *func)) || segmentReferrers.count(func->name)) { primaryFuncs.insert(func->name); diff --git a/src/ir/module-splitting.h b/src/ir/module-splitting.h index 620993d2d..89e4dd2bb 100644 --- a/src/ir/module-splitting.h +++ b/src/ir/module-splitting.h @@ -47,11 +47,11 @@ namespace wasm::ModuleSplitting { static const Name LOAD_SECONDARY_MODULE("__load_secondary_module"); struct Config { - // The set of functions to keep in the primary module. All others are split - // out into the new secondary module. Must include the start function if it + // The set of functions to split into the secondary module. All others are + // kept in the primary module. Must not include the start function if it // exists. May or may not include imported functions, which are always kept in // the primary module regardless. - std::set<Name> primaryFuncs; + std::set<Name> secondaryFuncs; // Whether to import placeholder functions into the primary module that will // be called when a secondary function is called before the secondary module // has been loaded. diff --git a/src/tools/wasm-split/wasm-split.cpp b/src/tools/wasm-split/wasm-split.cpp index 1cfe5bad9..d26f6f1d6 100644 --- a/src/tools/wasm-split/wasm-split.cpp +++ b/src/tools/wasm-split/wasm-split.cpp @@ -221,7 +221,7 @@ void splitModule(const WasmSplitOptions& options) { std::set<Name> splitFuncs; if (options.profileFile.size()) { - // Use the profile to set `keepFuncs`. + // Use the profile to set `keepFuncs` and `splitFuncs`. uint64_t hash = hashFile(options.inputFiles[0]); getFunctionsToKeepAndSplit( wasm, hash, options.profileFile, keepFuncs, splitFuncs); @@ -319,7 +319,7 @@ void splitModule(const WasmSplitOptions& options) { // Actually perform the splitting ModuleSplitting::Config config; - config.primaryFuncs = std::move(keepFuncs); + config.secondaryFuncs = std::move(splitFuncs); if (options.importNamespace.size()) { config.importNamespace = options.importNamespace; } @@ -418,9 +418,6 @@ void multiSplitModule(const WasmSplitOptions& options) { config.usePlaceholders = false; config.importNamespace = ""; config.minimizeNewExportNames = true; - for (auto& func : wasm.functions) { - config.primaryFuncs.insert(func->name); - } for (auto& [mod, funcs] : moduleFuncs) { if (options.verbose) { std::cerr << "Splitting module " << mod << '\n'; @@ -428,9 +425,7 @@ void multiSplitModule(const WasmSplitOptions& options) { if (!options.quiet && funcs.empty()) { std::cerr << "warning: Module " << mod << " will be empty\n"; } - for (auto& func : funcs) { - config.primaryFuncs.erase(Name(func)); - } + config.secondaryFuncs = std::set<Name>(funcs.begin(), funcs.end()); auto splitResults = ModuleSplitting::splitFunctions(wasm, config); // TODO: symbolMap, placeholderMap, emitModuleNames // TODO: Support --emit-text and use .wast in that case. diff --git a/test/example/module-splitting.cpp b/test/example/module-splitting.cpp index 81f095f48..b55beb1d3 100644 --- a/test/example/module-splitting.cpp +++ b/test/example/module-splitting.cpp @@ -28,14 +28,21 @@ void do_test(const std::set<Name>& keptFuncs, std::string&& module) { valid = validator.validate(*primary); assert(valid && "before invalid!"); + std::set<Name> splitFuncs; + for (auto& func : primary->functions) { + splitFuncs.insert(func->name); + } + std::cout << "Before:\n"; std::cout << *primary.get(); std::cout << "Keeping: "; if (keptFuncs.size()) { auto it = keptFuncs.begin(); + splitFuncs.erase(*it); std::cout << *it++; while (it != keptFuncs.end()) { + splitFuncs.erase(*it); std::cout << ", " << *it++; } } else { @@ -44,7 +51,7 @@ void do_test(const std::set<Name>& keptFuncs, std::string&& module) { std::cout << "\n"; ModuleSplitting::Config config; - config.primaryFuncs = keptFuncs; + config.secondaryFuncs = std::move(splitFuncs); config.newExportPrefix = "%"; auto secondary = splitFunctions(*primary, config).secondary; @@ -443,7 +450,6 @@ void test_minimized_exports() { Module primary; primary.features = FeatureSet::All; - std::set<Name> keep; Expression* callBody = nullptr; Builder builder(primary); @@ -453,7 +459,6 @@ void test_minimized_exports() { Name name = std::to_string(i); primary.addFunction( Builder::makeFunction(name, funcType, {}, builder.makeNop())); - keep.insert(name); callBody = builder.blockify(callBody, builder.makeCall(name, {}, Type::none)); @@ -470,7 +475,7 @@ void test_minimized_exports() { primary.addFunction(Builder::makeFunction("call", funcType, {}, callBody)); ModuleSplitting::Config config; - config.primaryFuncs = std::move(keep); + config.secondaryFuncs = {"call"}; config.newExportPrefix = "%"; config.minimizeNewExportNames = true; diff --git a/test/lit/wasm-split/multi-split.wast b/test/lit/wasm-split/multi-split.wast index 9206e60ee..d7fb56c07 100644 --- a/test/lit/wasm-split/multi-split.wast +++ b/test/lit/wasm-split/multi-split.wast @@ -7,8 +7,10 @@ ;; RUN: wasm-dis %t3.wasm | filecheck %s --check-prefix=CHECK-C (module - (type $ret-i32 (func (result i32))) ;; PRIMARY: (type $ret-i64 (func (result i64))) + + ;; PRIMARY: (type $ret-i32 (func (result i32))) + (type $ret-i32 (func (result i32))) (type $ret-i64 (func (result i64))) ;; PRIMARY: (type $ret-f32 (func (result f32))) (type $ret-f32 (func (result f32))) @@ -62,24 +64,24 @@ ) (i32.const 0) ) - ;; CHECK-B: (type $0 (func (result i32))) + ;; CHECK-B: (type $0 (func (result f32))) - ;; CHECK-B: (type $1 (func (result f32))) + ;; CHECK-B: (type $1 (func (result i32))) ;; CHECK-B: (type $2 (func (result i64))) - ;; CHECK-B: (import "" "table_3" (table $timport$0 2 funcref)) - - ;; CHECK-B: (import "" "table" (table $timport$1 1 funcref)) + ;; CHECK-B: (import "" "table_4" (table $timport$0 1 funcref)) ;; CHECK-B: (import "" "b" (func $C (result f32))) - ;; CHECK-B: (elem $0 (table $timport$0) (i32.const 0) func $B $1) + ;; CHECK-B: (import "" "c" (func $fimport$1 (result i32))) + + ;; CHECK-B: (elem $0 (i32.const 0) $B) ;; CHECK-B: (func $B (result i64) ;; CHECK-B-NEXT: (drop - ;; CHECK-B-NEXT: (call_ref $0 - ;; CHECK-B-NEXT: (ref.func $1) + ;; CHECK-B-NEXT: (call_ref $1 + ;; CHECK-B-NEXT: (ref.func $fimport$1) ;; CHECK-B-NEXT: ) ;; CHECK-B-NEXT: ) ;; CHECK-B-NEXT: (drop @@ -88,7 +90,7 @@ ;; CHECK-B-NEXT: ) ;; CHECK-B-NEXT: ) ;; CHECK-B-NEXT: (drop - ;; CHECK-B-NEXT: (call_ref $1 + ;; CHECK-B-NEXT: (call_ref $0 ;; CHECK-B-NEXT: (ref.func $C) ;; CHECK-B-NEXT: ) ;; CHECK-B-NEXT: ) @@ -112,33 +114,29 @@ ) (i64.const 0) ) - ;; CHECK-C: (type $0 (func (result i64))) + ;; CHECK-C: (type $0 (func (result i32))) - ;; CHECK-C: (type $1 (func (result i32))) + ;; CHECK-C: (type $1 (func (result i64))) ;; CHECK-C: (type $2 (func (result f32))) - ;; CHECK-C: (import "" "table_4" (table $timport$0 2 funcref)) + ;; CHECK-C: (import "" "table_6" (table $timport$0 1 funcref)) - ;; CHECK-C: (import "" "table_3" (table $timport$1 2 funcref)) + ;; CHECK-C: (import "" "c" (func $fimport$0 (result i32))) - ;; CHECK-C: (elem $0 (table $timport$0) (i32.const 0) func $0 $C) + ;; CHECK-C: (import "" "d" (func $fimport$1 (result i64))) - ;; CHECK-C: (func $0 (result i64) - ;; CHECK-C-NEXT: (call_indirect (type $0) - ;; CHECK-C-NEXT: (i32.const 0) - ;; CHECK-C-NEXT: ) - ;; CHECK-C-NEXT: ) + ;; CHECK-C: (elem $0 (i32.const 0) $C) ;; CHECK-C: (func $C (result f32) ;; CHECK-C-NEXT: (drop - ;; CHECK-C-NEXT: (call_ref $1 - ;; CHECK-C-NEXT: (ref.func $3) + ;; CHECK-C-NEXT: (call_ref $0 + ;; CHECK-C-NEXT: (ref.func $fimport$0) ;; CHECK-C-NEXT: ) ;; CHECK-C-NEXT: ) ;; CHECK-C-NEXT: (drop - ;; CHECK-C-NEXT: (call_ref $0 - ;; CHECK-C-NEXT: (ref.func $2) + ;; CHECK-C-NEXT: (call_ref $1 + ;; CHECK-C-NEXT: (ref.func $fimport$1) ;; CHECK-C-NEXT: ) ;; CHECK-C-NEXT: ) ;; CHECK-C-NEXT: (drop @@ -169,52 +167,50 @@ ) ;; PRIMARY: (table $0 1 funcref) -;; PRIMARY: (table $1 2 funcref) +;; PRIMARY: (table $1 1 funcref) -;; PRIMARY: (table $2 2 funcref) +;; PRIMARY: (table $2 1 funcref) ;; PRIMARY: (elem $0 (table $0) (i32.const 0) funcref (item (ref.null nofunc))) -;; PRIMARY: (elem $1 (table $1) (i32.const 0) funcref (item (ref.null nofunc)) (item (ref.null nofunc))) +;; PRIMARY: (elem $1 (table $1) (i32.const 0) funcref (item (ref.null nofunc))) -;; PRIMARY: (elem $2 (table $2) (i32.const 0) funcref (item (ref.null nofunc)) (item (ref.null nofunc))) +;; PRIMARY: (elem $2 (table $2) (i32.const 0) funcref (item (ref.null nofunc))) -;; PRIMARY: (export "a" (func $0)) +;; PRIMARY: (export "a" (func $1)) -;; PRIMARY: (export "b" (func $1)) +;; PRIMARY: (export "b" (func $3)) ;; PRIMARY: (export "table" (table $0)) -;; PRIMARY: (export "table_3" (table $1)) +;; PRIMARY: (export "c" (func $0)) + +;; PRIMARY: (export "table_4" (table $1)) + +;; PRIMARY: (export "d" (func $2)) + +;; PRIMARY: (export "table_6" (table $2)) + +;; PRIMARY: (func $0 (result i32) +;; PRIMARY-NEXT: (call_indirect (type $ret-i32) +;; PRIMARY-NEXT: (i32.const 0) +;; PRIMARY-NEXT: ) +;; PRIMARY-NEXT: ) -;; PRIMARY: (export "table_4" (table $2)) +;; PRIMARY: (func $1 (result i64) +;; PRIMARY-NEXT: (call_indirect (type $ret-i64) +;; PRIMARY-NEXT: (i32.const 0) +;; PRIMARY-NEXT: ) +;; PRIMARY-NEXT: ) -;; PRIMARY: (func $0 (result i64) +;; PRIMARY: (func $2 (result i64) ;; PRIMARY-NEXT: (call_indirect (type $ret-i64) ;; PRIMARY-NEXT: (i32.const 0) ;; PRIMARY-NEXT: ) ;; PRIMARY-NEXT: ) -;; PRIMARY: (func $1 (result f32) +;; PRIMARY: (func $3 (result f32) ;; PRIMARY-NEXT: (call_indirect (type $ret-f32) -;; PRIMARY-NEXT: (i32.const 1) +;; PRIMARY-NEXT: (i32.const 0) ;; PRIMARY-NEXT: ) ;; PRIMARY-NEXT: ) - -;; CHECK-B: (func $1 (result i32) -;; CHECK-B-NEXT: (call_indirect (type $0) -;; CHECK-B-NEXT: (i32.const 0) -;; CHECK-B-NEXT: ) -;; CHECK-B-NEXT: ) - -;; CHECK-C: (func $2 (result i64) -;; CHECK-C-NEXT: (call_indirect (type $0) -;; CHECK-C-NEXT: (i32.const 0) -;; CHECK-C-NEXT: ) -;; CHECK-C-NEXT: ) - -;; CHECK-C: (func $3 (result i32) -;; CHECK-C-NEXT: (call_indirect (type $1) -;; CHECK-C-NEXT: (i32.const 1) -;; CHECK-C-NEXT: ) -;; CHECK-C-NEXT: ) |