diff options
author | Alon Zakai <azakai@google.com> | 2023-10-19 09:11:36 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-19 16:11:36 +0000 |
commit | be6a3393c36ccc1a0cb0d79b116cbe48e169f93b (patch) | |
tree | 8240468a78e62b6d18d747c865557d69f01b4b9f | |
parent | f79b5aa26b1fc722853e56b541cd35128786ef6b (diff) | |
download | binaryen-be6a3393c36ccc1a0cb0d79b116cbe48e169f93b.tar.gz binaryen-be6a3393c36ccc1a0cb0d79b116cbe48e169f93b.tar.bz2 binaryen-be6a3393c36ccc1a0cb0d79b116cbe48e169f93b.zip |
RemoveUnusedModuleElements: Make exports skip trampolines (#6026)
If we export a function that just calls another function, we can export that one
instead. Then the one in the middle may be unused,
function foo() {
return bar();
}
export foo; // can be an export of bar
This saves a few bytes in rare cases, but probably more important is that it saves
the trampoline, so if this is on a hot path, we save a call.
Context: emscripten-core/emscripten#20478 (comment)
In general this is not needed as inlining helps us out by inlining foo() into the
caller (since foo is tiny, that always ends up happening). But exports are a case
the inliner cannot handle, so we do it here.
-rw-r--r-- | src/passes/RemoveUnusedModuleElements.cpp | 61 | ||||
-rw-r--r-- | test/lit/merge/chain.wat | 6 | ||||
-rw-r--r-- | test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast | 7 | ||||
-rw-r--r-- | test/lit/passes/extract-function.wast | 14 | ||||
-rw-r--r-- | test/lit/passes/remove-unused-module-elements-refs.wast | 14 | ||||
-rw-r--r-- | test/lit/passes/remove-unused-module-elements_all-features.wast | 245 | ||||
-rw-r--r-- | test/metadce/threaded.wast.dced | 15 | ||||
-rw-r--r-- | test/metadce/threaded_cycle.wast.dced | 20 | ||||
-rw-r--r-- | test/passes/remove-unused-nonfunction-module-elements_all-features.txt | 6 | ||||
-rw-r--r-- | test/wasm2js/dot_import.2asm.js | 6 | ||||
-rw-r--r-- | test/wasm2js/dot_import.2asm.js.opt | 6 | ||||
-rw-r--r-- | test/wasm2js/emscripten.2asm.js | 6 | ||||
-rw-r--r-- | test/wasm2js/emscripten.2asm.js.opt | 6 | ||||
-rw-r--r-- | test/wasm2js/func_ptrs.2asm.js | 7 |
14 files changed, 314 insertions, 105 deletions
diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp index e082f8e15..cf1f265bc 100644 --- a/src/passes/RemoveUnusedModuleElements.cpp +++ b/src/passes/RemoveUnusedModuleElements.cpp @@ -601,6 +601,8 @@ struct RemoveUnusedModuleElements : public Pass { : rootAllFunctions(rootAllFunctions) {} void run(Module* module) override { + prepare(module); + std::vector<ModuleElement> roots; // Module start is a root. if (module->start.is()) { @@ -712,6 +714,65 @@ struct RemoveUnusedModuleElements : public Pass { // to a function from an element segment, we may be able to remove // that function, etc.) } + + // Do simple work that prepares the module to be efficiently optimized. + void prepare(Module* module) { + // If a function export is a function that just calls another function, we + // can export that one directly. Doing so might make the function in the + // middle unused: + // + // (export "export" (func $middle)) + // (func $middle + // (call $real) + // ) + // + // => + // + // (export "export" (func $real)) ;; this changed + // (func $middle + // (call $real) + // ) + // + // (Normally this is not needed, as inlining will end up removing such + // silly trampoline functions, but the case of an import being exported does + // not have any code for inlining to work with, so we need to handle it + // directly.) + for (auto& exp : module->exports) { + if (exp->kind != ExternalKind::Function) { + continue; + } + + auto* func = module->getFunction(exp->value); + if (!func->body) { + continue; + } + + auto* call = func->body->dynCast<Call>(); + if (!call) { + continue; + } + + // Don't do this if the type is different, as then we might be + // changing the external interface to the module. + auto* calledFunc = module->getFunction(call->target); + if (calledFunc->type != func->type) { + continue; + } + + // Finally, all the params must simply be forwarded. + auto ok = true; + for (Index i = 0; i < call->operands.size(); i++) { + auto* get = call->operands[i]->dynCast<LocalGet>(); + if (!get || get->index != i) { + ok = false; + break; + } + } + if (ok) { + exp->value = calledFunc->name; + } + } + } }; Pass* createRemoveUnusedModuleElementsPass() { diff --git a/test/lit/merge/chain.wat b/test/lit/merge/chain.wat index 528b20d0e..76004e9bd 100644 --- a/test/lit/merge/chain.wat +++ b/test/lit/merge/chain.wat @@ -13,12 +13,8 @@ ;; CHECK: (export "g" (func $0)) -;; CHECK: (export "h" (func $0_2)) +;; CHECK: (export "h" (func $0)) ;; CHECK: (func $0 (type $0) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) - -;; CHECK: (func $0_2 (type $0) -;; CHECK-NEXT: (call $0) -;; CHECK-NEXT: ) diff --git a/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast b/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast index e0045579d..907891aee 100644 --- a/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast +++ b/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast @@ -18,7 +18,7 @@ ;; CHECK: (export "t1" (func $t1)) - ;; CHECK: (export "t2" (func $t2)) + ;; CHECK: (export "t2" (func $fib)) ;; CHECK: (export "t3" (func $t3)) @@ -155,11 +155,6 @@ ) ) ) - ;; CHECK: (func $t2 (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (call $fib - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) (func $t2 (export "t2") (type $t0) (param $p0 i32) (result i32) (call $fib (local.get $p0) diff --git a/test/lit/passes/extract-function.wast b/test/lit/passes/extract-function.wast index 9258f8c63..e4b804abe 100644 --- a/test/lit/passes/extract-function.wast +++ b/test/lit/passes/extract-function.wast @@ -5,15 +5,6 @@ ;; RUN: foreach %s %t wasm-opt --extract-function-index --pass-arg=extract-function-index@0 -S -o - | filecheck %s (module - ;; CHECK: (type $0 (func)) - - ;; CHECK: (import "env" "bar" (func $bar)) - - ;; CHECK: (export "foo" (func $foo)) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (call $bar) - ;; CHECK-NEXT: ) (func $foo (call $bar) ) @@ -27,6 +18,11 @@ ) ) +;; CHECK: (type $0 (func)) + +;; CHECK: (import "env" "bar" (func $bar)) + +;; CHECK: (export "foo" (func $bar)) (module ;; Use another function in the table, but the table is not used in the ;; extracted function diff --git a/test/lit/passes/remove-unused-module-elements-refs.wast b/test/lit/passes/remove-unused-module-elements-refs.wast index 00ea9767f..377639e51 100644 --- a/test/lit/passes/remove-unused-module-elements-refs.wast +++ b/test/lit/passes/remove-unused-module-elements-refs.wast @@ -656,24 +656,18 @@ (ref.func $d) )) - ;; CHECK: (export "export" (func $export)) - - ;; CHECK: (func $export (type $void) - ;; CHECK-NEXT: (call $b) - ;; CHECK-NEXT: ) - ;; OPEN_WORLD: (export "export" (func $export)) - - ;; OPEN_WORLD: (func $export (type $void) - ;; OPEN_WORLD-NEXT: (call $b) - ;; OPEN_WORLD-NEXT: ) (func $export (export "export") ;; Call $b but not $a or $c (call $b) ) + ;; CHECK: (export "export" (func $b)) + ;; CHECK: (func $a (type $void) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (export "export" (func $b)) + ;; OPEN_WORLD: (func $a (type $void) ;; OPEN_WORLD-NEXT: (call_ref $void ;; OPEN_WORLD-NEXT: (struct.get $vtable 0 diff --git a/test/lit/passes/remove-unused-module-elements_all-features.wast b/test/lit/passes/remove-unused-module-elements_all-features.wast index 2979d1cd5..b5c5d701e 100644 --- a/test/lit/passes/remove-unused-module-elements_all-features.wast +++ b/test/lit/passes/remove-unused-module-elements_all-features.wast @@ -19,7 +19,7 @@ ;; CHECK: (export "memory" (memory $0)) - ;; CHECK: (export "exported" (func $exported)) + ;; CHECK: (export "exported" (func $called2)) ;; CHECK: (export "other1" (func $other1)) @@ -64,9 +64,6 @@ (func $called_indirect (type $0) (nop) ) - ;; CHECK: (func $exported (type $0) - ;; CHECK-NEXT: (call $called2) - ;; CHECK-NEXT: ) (func $exported (type $0-dupe) (call $called2) ) @@ -459,15 +456,15 @@ (func $waka) ;; used in table ) (module ;; one is exported, and one->two->int global, whose init->imported - ;; CHECK: (type $0 (func (result i32))) + ;; CHECK: (type $0 (func (param i32) (result i32))) - ;; CHECK: (type $1 (func)) + ;; CHECK: (type $1 (func (result i32))) - ;; CHECK: (type $2 (func (param i32) (result i32))) + ;; CHECK: (type $2 (func)) ;; CHECK: (import "env" "imported" (global $imported i32)) (import "env" "imported" (global $imported i32)) - ;; CHECK: (import "env" "_puts" (func $_puts (type $2) (param i32) (result i32))) + ;; CHECK: (import "env" "_puts" (func $_puts (type $0) (param i32) (result i32))) (import "env" "forgetme" (global $forgetme i32)) (import "env" "_puts" (func $_puts (param i32) (result i32))) (import "env" "forget_puts" (func $forget_puts (param i32) (result i32))) @@ -478,32 +475,26 @@ (global $forglobal.get (mut i32) (i32.const 500)) ;; CHECK: (global $exp_glob i32 (i32.const 600)) (global $exp_glob i32 (i32.const 600)) - ;; CHECK: (export "one" (func $one)) + ;; CHECK: (export "one" (func $two)) (export "one" (func $one)) - ;; CHECK: (export "three" (func $three)) + ;; CHECK: (export "three" (func $four)) (export "three" (func $three)) ;; CHECK: (export "exp_glob" (global $exp_glob)) (export "exp_glob" (global $exp_glob)) (start $starter) - ;; CHECK: (func $one (type $0) (result i32) - ;; CHECK-NEXT: (call $two) - ;; CHECK-NEXT: ) (func $one (result i32) (call $two) ) - ;; CHECK: (func $two (type $0) (result i32) + ;; CHECK: (func $two (type $1) (result i32) ;; CHECK-NEXT: (global.get $int) ;; CHECK-NEXT: ) (func $two (result i32) (global.get $int) ) - ;; CHECK: (func $three (type $1) - ;; CHECK-NEXT: (call $four) - ;; CHECK-NEXT: ) (func $three (call $four) ) - ;; CHECK: (func $four (type $1) + ;; CHECK: (func $four (type $2) ;; CHECK-NEXT: (global.set $set ;; CHECK-NEXT: (i32.const 200) ;; CHECK-NEXT: ) @@ -746,6 +737,7 @@ ) ) ) + ;; CHECK: (export "func" (func $0)) ;; CHECK: (func $0 (type $0) @@ -761,3 +753,220 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) +(module + ;; When we export a function that calls another, we can export the called + ;; function, skipping the one in the middle. The exports of $middle and + ;; $other-middle can be changed to their targets here. + + ;; CHECK: (type $0 (func)) + + ;; CHECK: (import "a" "b" (func $import (type $0))) + (import "a" "b" (func $import)) + + ;; CHECK: (export "export-import" (func $import)) + (export "export-import" (func $import)) + + ;; CHECK: (export "export-middle" (func $import)) + (export "export-middle" (func $middle)) + + ;; CHECK: (export "export-other-middle" (func $internal)) + (export "export-other-middle" (func $other-middle)) + + ;; CHECK: (export "export-internal" (func $internal)) + (export "export-internal" (func $internal)) + + (func $middle + (call $import) + ) + + (func $other-middle + (call $internal) + ) + + ;; CHECK: (func $internal (type $0) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $internal + ) +) + +;; As above, but we do not do that optimization when it would change the +;; exported type. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $A (func)) + (type $A (func)) + ;; CHECK: (type $B (func)) + (type $B (func)) + ) + + ;; CHECK: (import "a" "a" (func $import-A (type $A))) + (import "a" "a" (func $import-A (type $A))) + ;; CHECK: (import "b" "b" (func $import-B (type $B))) + (import "b" "b" (func $import-B (type $B))) + + ;; CHECK: (export "export-import-A" (func $import-A)) + (export "export-import-A" (func $import-A)) + + ;; CHECK: (export "export-import-B" (func $import-B)) + (export "export-import-B" (func $import-B)) + + ;; CHECK: (export "export-middle-A-A" (func $import-A)) + (export "export-middle-A-A" (func $middle-A-A)) + + ;; CHECK: (export "export-middle-A-B" (func $middle-A-B)) + (export "export-middle-A-B" (func $middle-A-B)) + + ;; CHECK: (export "export-middle-B-A" (func $middle-B-A)) + (export "export-middle-B-A" (func $middle-B-A)) + + ;; CHECK: (export "export-middle-B-B" (func $import-B)) + (export "export-middle-B-B" (func $middle-B-B)) + + (func $middle-A-A (type $A) + (call $import-A) + ) + + ;; CHECK: (func $middle-A-B (type $A) + ;; CHECK-NEXT: (call $import-B) + ;; CHECK-NEXT: ) + (func $middle-A-B (type $A) + (call $import-B) + ) + + ;; CHECK: (func $middle-B-A (type $B) + ;; CHECK-NEXT: (call $import-A) + ;; CHECK-NEXT: ) + (func $middle-B-A (type $B) + (call $import-A) + ) + + (func $middle-B-B (type $B) + (call $import-B) + ) +) + +;; As above, but checking for parameters: It's ok to pass values through, but +;; not to do anything else. +(module + ;; CHECK: (type $0 (func (param i32))) + + ;; CHECK: (import "a" "b" (func $import (type $0) (param i32))) + (import "a" "b" (func $import (param i32))) + + ;; CHECK: (export "export-import" (func $import)) + (export "export-import" (func $import)) + + ;; CHECK: (export "export-middle" (func $import)) + (export "export-middle" (func $middle)) + + ;; CHECK: (export "export-middle-local" (func $middle-local)) + (export "export-middle-local" (func $middle-local)) + + ;; CHECK: (export "export-middle-other" (func $middle-other)) + (export "export-middle-other" (func $middle-other)) + + ;; CHECK: (export "export-middle-noncall" (func $middle-noncall)) + (export "export-middle-noncall" (func $middle-noncall)) + + (func $middle (param $x i32) + ;; This extra local is not a problem. + (local $y i32) + (call $import + (local.get $x) + ) + ) + + ;; CHECK: (func $middle-local (type $0) (param $x i32) + ;; CHECK-NEXT: (local $y i32) + ;; CHECK-NEXT: (call $import + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $middle-local (param $x i32) + (local $y i32) + (call $import + ;; Now we get the local instead of the param, so we cannot optimize. + (local.get $y) + ) + ) + + ;; CHECK: (func $middle-other (type $0) (param $x i32) + ;; CHECK-NEXT: (call $import + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $middle-other (param $x i32) + (call $import + ;; Something other than local.get, so we cannot optimize. + (i32.const 1) + ) + ) + + ;; CHECK: (func $middle-noncall (type $0) (param $x i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $middle-noncall (param $x i32) + ;; Not even a call here. + (drop + (i32.const 1) + ) + ) +) + +;; Function with two parameters: we can only optimize when the arguments are in +;; the right order. +;; +;; Also test with a return value. +(module + ;; CHECK: (type $0 (func (param i32 i32) (result f64))) + + ;; CHECK: (import "a" "b" (func $import (type $0) (param i32 i32) (result f64))) + (import "a" "b" (func $import (param i32) (param i32) (result f64))) + + ;; CHECK: (export "export-middle-right" (func $import)) + (export "export-middle-right" (func $middle-right)) + + ;; CHECK: (export "export-middle-wrong" (func $middle-wrong)) + (export "export-middle-wrong" (func $middle-wrong)) + + (func $middle-right (param $x i32) (param $y i32) (result f64) + (call $import + (local.get $x) + (local.get $y) + ) + ) + + ;; CHECK: (func $middle-wrong (type $0) (param $x i32) (param $y i32) (result f64) + ;; CHECK-NEXT: (call $import + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $middle-wrong (param $x i32) (param $y i32) (result f64) + ;; The local.gets are reversed here, so we cannot optimize. + (call $import + (local.get $y) + (local.get $x) + ) + ) +) + +(module + ;; As above, but with a return_call. We can optimize it like a call. + + ;; CHECK: (type $0 (func)) + + ;; CHECK: (import "a" "b" (func $import (type $0))) + (import "a" "b" (func $import)) + + ;; CHECK: (export "export-middle" (func $import)) + (export "export-middle" (func $middle)) + + (func $middle + (return_call $import) + ) +) diff --git a/test/metadce/threaded.wast.dced b/test/metadce/threaded.wast.dced index 0d5d2f98d..3157a360a 100644 --- a/test/metadce/threaded.wast.dced +++ b/test/metadce/threaded.wast.dced @@ -3,20 +3,11 @@ (import "env" "js_func4" (func $js_func_4 (type $0))) (import "env" "js_func3" (func $js_func_3 (type $0))) (import "env" "js_func2" (func $js_func_2 (type $0))) - (export "wasm_func1" (func $wasm_func_1)) - (export "wasm_func2" (func $wasm_func_2)) - (export "wasm_func3" (func $wasm_func_3)) + (export "wasm_func1" (func $js_func_2)) + (export "wasm_func2" (func $js_func_3)) + (export "wasm_func3" (func $js_func_4)) (export "wasm_func4" (func $wasm_func_4)) (func $wasm_func_4 (type $0) (nop) ) - (func $wasm_func_3 (type $0) - (call $js_func_4) - ) - (func $wasm_func_2 (type $0) - (call $js_func_3) - ) - (func $wasm_func_1 (type $0) - (call $js_func_2) - ) ) diff --git a/test/metadce/threaded_cycle.wast.dced b/test/metadce/threaded_cycle.wast.dced index 302cb3faf..1b30eadc5 100644 --- a/test/metadce/threaded_cycle.wast.dced +++ b/test/metadce/threaded_cycle.wast.dced @@ -4,20 +4,8 @@ (import "env" "js_func3" (func $js_func_3 (type $0))) (import "env" "js_func2" (func $js_func_2 (type $0))) (import "env" "js_func1" (func $js_func_1 (type $0))) - (export "wasm_func1" (func $wasm_func_1)) - (export "wasm_func2" (func $wasm_func_2)) - (export "wasm_func3" (func $wasm_func_3)) - (export "wasm_func4" (func $wasm_func_4)) - (func $wasm_func_4 (type $0) - (call $js_func_1) - ) - (func $wasm_func_3 (type $0) - (call $js_func_4) - ) - (func $wasm_func_2 (type $0) - (call $js_func_3) - ) - (func $wasm_func_1 (type $0) - (call $js_func_2) - ) + (export "wasm_func1" (func $js_func_2)) + (export "wasm_func2" (func $js_func_3)) + (export "wasm_func3" (func $js_func_4)) + (export "wasm_func4" (func $js_func_1)) ) diff --git a/test/passes/remove-unused-nonfunction-module-elements_all-features.txt b/test/passes/remove-unused-nonfunction-module-elements_all-features.txt index d19fcc514..186bdd69b 100644 --- a/test/passes/remove-unused-nonfunction-module-elements_all-features.txt +++ b/test/passes/remove-unused-nonfunction-module-elements_all-features.txt @@ -6,7 +6,7 @@ (table $0 1 1 funcref) (elem $0 (i32.const 0) $called_indirect) (export "memory" (memory $0)) - (export "exported" (func $exported)) + (export "exported" (func $called2)) (export "other1" (func $other1)) (export "other2" (func $other2)) (start $start) @@ -240,8 +240,8 @@ (global $int (mut i32) (global.get $imported)) (global $set (mut i32) (i32.const 100)) (global $exp_glob i32 (i32.const 600)) - (export "one" (func $one)) - (export "three" (func $three)) + (export "one" (func $two)) + (export "three" (func $four)) (export "exp_glob" (global $exp_glob)) (func $one (type $1) (result i32) (call $two) diff --git a/test/wasm2js/dot_import.2asm.js b/test/wasm2js/dot_import.2asm.js index a35eabe95..0cd48aaf1 100644 --- a/test/wasm2js/dot_import.2asm.js +++ b/test/wasm2js/dot_import.2asm.js @@ -13,12 +13,8 @@ function asmFunc(imports) { var Math_sqrt = Math.sqrt; var mod_ule = imports["mod.ule"]; var base = mod_ule["ba.se"]; - function $0() { - base(); - } - return { - "exported": $0 + "exported": base }; } diff --git a/test/wasm2js/dot_import.2asm.js.opt b/test/wasm2js/dot_import.2asm.js.opt index a35eabe95..0cd48aaf1 100644 --- a/test/wasm2js/dot_import.2asm.js.opt +++ b/test/wasm2js/dot_import.2asm.js.opt @@ -13,12 +13,8 @@ function asmFunc(imports) { var Math_sqrt = Math.sqrt; var mod_ule = imports["mod.ule"]; var base = mod_ule["ba.se"]; - function $0() { - base(); - } - return { - "exported": $0 + "exported": base }; } diff --git a/test/wasm2js/emscripten.2asm.js b/test/wasm2js/emscripten.2asm.js index 8ba8564ce..52412f676 100644 --- a/test/wasm2js/emscripten.2asm.js +++ b/test/wasm2js/emscripten.2asm.js @@ -61,10 +61,6 @@ function asmFunc(imports) { exported(1 | 0) | 0; } - function other() { - main(); - } - function foo() { wasm2js_trap(); } @@ -222,7 +218,7 @@ function asmFunc(imports) { return { "main": main, - "other": other, + "other": main, "__growWasmMemory": __growWasmMemory, "exported": exported, "sub_zero": sub_zero, diff --git a/test/wasm2js/emscripten.2asm.js.opt b/test/wasm2js/emscripten.2asm.js.opt index caef23896..1faf11933 100644 --- a/test/wasm2js/emscripten.2asm.js.opt +++ b/test/wasm2js/emscripten.2asm.js.opt @@ -70,10 +70,6 @@ function asmFunc(imports) { FUNCTION_TABLE[HEAP32[257]](); } - function other() { - main(); - } - function foo() { wasm2js_trap(); } @@ -217,7 +213,7 @@ function asmFunc(imports) { return { "main": main, - "other": other, + "other": main, "__growWasmMemory": __growWasmMemory, "exported": internal, "sub_zero": sub_zero, diff --git a/test/wasm2js/func_ptrs.2asm.js b/test/wasm2js/func_ptrs.2asm.js index 4b7c4fd44..ccd220152 100644 --- a/test/wasm2js/func_ptrs.2asm.js +++ b/test/wasm2js/func_ptrs.2asm.js @@ -27,16 +27,11 @@ function asmFunc(imports) { return a - 2 | 0 | 0; } - function $6($0) { - $0 = $0 | 0; - print($0 | 0); - } - return { "one": $3, "two": $4, "three": $5, - "four": $6 + "four": print }; } |