| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously the relooper would do some optimizations when deciding when to use an if vs a switch, how to group blocks, etc. This PR adds an additional pre-optimization phase with some basic but useful simplify-cfg style passes,
* Skip empty blocks when they have just one exit.
* Merge exiting branches when they are equivalent.
* Canonicalize block contents to make such comparisons more useful.
* Turn a trivial one-target switch into a simple branch.
This can help in noticeable ways when running the rereloop pass, e.g. on LLVM wasm backend output.
Also:
* Binaryen C API changes to the relooper, which now gets a Module for its constructor. It needs it for the optimizations, as it may construct new nodes.
* Many relooper-fuzzer improvements.
* Clean up HashType usage.
|
|
|
|
|
| |
That is the correct order in the text format, wabt errors otherwise.
See AssemblyScript/assemblyscript#310
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fixes #1649
This moves us to a single object for functions, which can be imported or nor, and likewise for globals (as a result, GetGlobals do not need to check if the global is imported or not, etc.). All imported things now inherit from Importable, which has the module and base of the import, and if they are set then it is an import.
For convenient iteration, there are a few helpers like
ModuleUtils::iterDefinedGlobals(wasm, [&](Global* global) {
.. use global ..
});
as often iteration only cares about imported or defined (non-imported) things.
|
|
|
|
|
|
| |
* Error if there are more locals than browsers allow (50,000). We usually just warn about stuff like this, but we do need some limit (or else we hang or OOM), and if so, why not use the agreed-upon Web limit.
* Do not generate nice string names for locals in binary parsing - the name is just $var$x instead of $x, so not much benefit, and worse as our names are interned this is actually slow (which is why the fuzz testcase here hangs instead of OOMing).
Testcases and bugreport in #1663.
|
|
|
|
|
| |
This allows using imports in the table.
Fixes #1645
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This adds a new IR, "Stack IR". This represents wasm at a very low level, as a simple stream of instructions, basically the same as wasm's binary format. This is unlike Binaryen IR which is structured and in a tree format.
This gives some small wins on binary sizes, less than 1% in most cases, usually 0.25-0.50% or so. That's not much by itself, but looking forward this prepares us for multi-value, which we really need an IR like this to be able to optimize well. Also, it's possible there is more we can do already - currently there are just a few stack IR optimizations implemented,
DCE
local2stack - check if a set_local/get_local pair can be removed, which keeps the set's value on the stack, which if the stars align it can be popped instead of the get.
Block removal - remove any blocks with no branches, as they are valid in wasm binary format.
Implementation-wise, the IR is defined in wasm-stack.h. A new StackInst is defined, representing a single instruction. Most are simple reflections of Binaryen IR (an add, a load, etc.), and just pointers to them. Control flow constructs are expanded into multiple instructions, like a block turns into a block begin and end, and we may also emit extra unreachables to handle the fact Binaryen IR has unreachable blocks/ifs/loops but wasm does not. Overall, all the Binaryen IR differences with wasm vanish on the way to stack IR.
Where this IR lives: Each Function now has a unique_ptr to stack IR, that is, a function may have stack IR alongside the main IR. If the stack IR is present, we write it out during binary writing; if not, we do the same binaryen IR => wasm binary process as before (this PR should not affect speed there). This design lets us use normal Passes on stack IR, in particular this PR defines 3 passes:
Generate stack IR
Optimize stack IR (might be worth splitting out into separate passes eventually)
Print stack IR for debugging purposes
Having these as normal passes is convenient as then they can run in parallel across functions and all the other conveniences of our current Pass system. However, a downside of keeping the second IR as an option on Functions, and using normal Passes to operate on it, means that we may get out of sync: if you generate stack IR, then modify binaryen IR, then the stack IR may no longer be valid (for example, maybe you removed locals or modified instructions in place etc.). To avoid that, Passes now define if they modify Binaryen IR or not; if they do, we throw away the stack IR.
Miscellaneous notes:
Just writing Stack IR, then writing to binary - no optimizations - is 20% slower than going directly to binary, which is one reason why we still support direct writing. This does lead to some "fun" C++ template code to make that convenient: there is a single StackWriter class, templated over the "mode", which is either Binaryen2Binary (direct writing), Binaryen2Stack, or Stack2Binary. This avoids a lot of boilerplate as the 3 modes share a lot of code in overlapping ways.
Stack IR does not support source maps / debug info. We just don't use that IR if debug info is present.
A tiny text format comment (if emitting non-minified text) indicates stack IR is present, if it is ((; has Stack IR ;)). This may help with debugging, just in case people forget. There is also a pass to print out the stack IR for debug purposes, as mentioned above.
The sieve binaryen.js test was actually not validating all along - these new opts broke it in a more noticeable manner. Fixed.
Added extra checks in pass-debug mode, to verify that if stack IR should have been thrown out, it was. This should help avoid any confusion with the IR being invalid.
Added a comment about the possible future of stack IR as the main IR, depending on optimization results, following some discussion earlier today.
|
|
|
|
|
|
|
| |
On the testcase from https://github.com/tweag/asterius/issues/19#issuecomment-393052653 this makes us almost 3x faster, and use 25% less memory.
The main improvement here is to simplify and optimize the data structures the validator uses to validate br targets: use unordered maps, and use one less of them. Also some speedups from using that map more effectively (use of iterators to avoid multiple lookups).
Also move the duplicate-node checks to the internal IR validation section, which makes more sense anyhow (it's not wasm validation, it's internal IR validation, which like the check for stale internal types, we do only if debugging).
|
|
|
|
|
|
|
|
| |
* optimize more simple math operations: mul of 0, or of 0, and of 0, mul of 1, mul of a power of 2, urem of a power of 2
* fix asm2wasm callImport parsing: the optimizer may get rid of the added offset to a function table
* update js builds
|
|
|
|
|
|
|
|
| |
Refactor ThreadPool code for clarity and to fix some bugs with using the pool from different threads in parallel.
We have a singleton pool, and need to ensure it is created only once and used only by one thread at a time. This model is a simple way to ensure we use a number of threads equal to the number of cores, more or less (a pool per Module might lead to number of cores * number of Modules being optimized).
This refactoring adds a parent pointer in the worker threads (giving them direct access to the pool makes it simpler to make sure that pool and thread creation and teardown are threadsafe). This commit also adds proper locking around pool creation and pool usage.
|
|
|
|
|
|
| |
fixes #1369
* Update binaries and kitchen-sink test
|
|
|
|
|
| |
Followup to #1357. This moves the optimization settings into pass.h, and uses it from there in the various places.
This also splits up huge lines from the tracing code, which put all block children (whose number can be arbitrarily large) on one line. This seems to have caused random errors on the bots, I suspect from overflowing a buffer. Anyhow, it's much more clear to split the lines at a reasonable length.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Add optimize, shrink level and debug info options to C/JS
* Add instantiate functionality for creating additional unique instances of the API
* Use a workaround when running tests in node
Tests misuse a module as a script by concatenating, so instead of catching this case in the library, catch it there
* Update sieve test
Seems optimized output changed due to running with optimize levels 2/1 now
* Use the options with all pass runners
* Update relooper-fuzz C-API test
* Share defaults between tools and the C-API
* Add a test for optimize levels
* Unify node test support in check.by and auto_update_tests.py
* Also add getters for optimize levels and test them
* Also test debugInfo
* Add debug info to C tests that used it as well
* Fix missing NODEJS import in auto_update_tests
* Detect node.js version (WASM support)
* Update hello-world JS test (now also runs with node)
* feature-test WebAssembly in node instead
* Document that these options apply globally, and where
* Make sure hello-world.js output doesn't differ between mozjs/node
|
|
|
| |
We can remove the memory/table (itself, or an import if imported) if they are not used. This is pretty minor on a large wasm file, but when reading small wasts it's very noticeable to have an unused memory and table all the time.
|
| |
|
|
|
|
| |
* Provide AddImport/AddExport for each element in the C-API
|
|
|
|
| |
Function type gets its own element rather than being a part of the call_indirect
(see WebAssembly/spec#599)
|
|
|
| |
Now also includes a test.
|
| |
|
| |
|
| |
|
|
|
|
|
|
| |
* don't emit a toplevel block if we don't need to, as in wasm it is a list context
* don't create unnecessary blocks in wasm reading
|
|
|
| |
Ignoring unreachable code in wasm binaries lets us avoid corner cases with unstructured code in wasm binaries that is a poor fit for Binaryen's structured IR.
|
|
|
|
| |
* emit optimal-size LEBs in section/subsection/function body sizes, instead of preallocating 5 bytes
|
|
|
|
|
|
| |
Support both syntax formats in input since the old spec
tests still need to be parsable.
|
| |
|
|
|
| |
This PR adds global variable support (addGlobal, getGlobal, setGlobal), host operations (currentMemory, growMemory), a few utility functions (removeImport, removeExport, getFunctionTypeBySignature with the latter being scheduled for removal once a better alternative is in place) and it introduces an additional argument to specify the result type in BinaryenBlock (effectively breaking the C-API but retaining previous behaviour by introducing the BinaryenUndefined() type for this purpose). Additionally, it enables compilation with exception support in build-js.sh as exceptions are thrown and caught when optimizing endless loops, intentionally resulting in an unreachable opcode. Affected test cases have been updated accordingly.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
See https://github.com/WebAssembly/binaryen/issues/914.
* extensible name section support: read function names, too
* c-api-unused-mem.txt: change expected size to match new name section
* * check subsection size matches
* print warning for unknown name subsections (including the local
section)
|
|
|
| |
New binaryen.js implementation, based on the C API underneath and with a JS-friendly API on top. See docs under docs/ for API details.
|
| |
|
|
|
|
| |
unruly (#928)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* an unreachable block is one with an unreachable child, plus no breaks
* document new difference between binaryen IR and wasm
* fix relooper missing finalize
* add a bunch of tests
* don't assume that test/*.wast files print to themselves exactly; print to from.wast. this allows wast tests with comments in them
* emit unreachable blocks as (block .. unreachable) unreachable
* if without else and unreachable ifTrue is still not unreachable, it should be none
* update wasm.js
* cleanups
* empty blocks have none type
|
| |
|
|
|
|
| |
TempRet0 if needed (otherwise we might remove it before we use it)
|
| |
|
|
|
|
|
|
|
|
| |
In wast files, the spec and WABT require imports to appear before any
non-import definitions (see also
https://github.com/WebAssembly/wabt/issues/152). This patch re-orders
visitModule in the wast printer to meet this requirement, and more or
less match the order of the binary sections. Also remove extraneous
whitespace around table definitions.
|
| |
|
|
|
|
|
| |
Otherwise when we export it as "$0" it's an undefined name.
The spec interpreter actually rejects this, although I think it's
intended to work, given the tests in export.wast. wabt also accepts it.
|
|
|
|
|
|
| |
Also updates the tests and has a few other changes for binary 0xc:
Update nop/unrechable opcodes
Fix for "name" section
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|