summaryrefslogtreecommitdiff
path: root/test
Commit message (Collapse)AuthorAgeFilesLines
* Don't try to optimize away unused names in RemoveUnusedBrs (#1750)Alon Zakai2018-11-1514-246/+225
| | | | | Rely on the dedicated pass for that. It's not worth the extra complexity to try, as we can't easily handle all the cases anyhow. Add another run of the dedicated name-removing pass in the default passes.
* MergeBlocks: canonicalize loop exit block position on the inside (#1736)Alon Zakai2018-11-148-77/+108
| | | | * move a loop exit block (block with a name, and one child which is the loop) into the loop in MergeBlocks, as that is better for other passes
* Handle EM_ASM functions in Tables (#1739)Jacob Gravelle2018-11-142-0/+77
| | | | | Not at all sure why we're seeing any there, but it's easy enough to handle that we might as well.
* Restructure ifs with a value (#1743)Alon Zakai2018-11-142-0/+113
| | | We previously had code to recreate an if from a block+branch when possible, but not when the block had a return value. This PR adds support to restructure that too, into an if with a value.
* ReFinalize fix (#1742)Alon Zakai2018-11-145-17/+62
| | | | | | | Handle a corner case in ReFinalize, which incrementally re-types code after changes. The problem is that if we need to figure out the type of a block, we look to the last element flowing out, or to breaks with values. If there is no such last element, and the breaks are not taken - they have unreachable values - then they don't tell us the block's proper type. We asserted that in such a case the block still had a type, and didn't handle this. To fix it, we could look on the parent to see what type would fit. However, it seem simpler to just remove untaken breaks/switches as part of ReFinalization - they carry no useful info anyhow. After removing them, if the block has no other signal of a concrete type, it can just be unreachable. This bug existed for at least 1.5 years - I didn't look back further. I think it was noticed by the fuzzer now due to recent fuzzing improvements and optimizer improvements, as I just saw this bug found a second time.
* Add wasm-emscripten-finalize flag to separate data segments into a file (#1741)Derek Schuff2018-11-142-0/+61
| | | | This writes the data section into a file suitable for use with emscripten's --memory-init-file flag
* Better fuzzing (#1735)Alon Zakai2018-11-131-1083/+777
| | | | | | * Recombine function pieces after randomly generating them, by creating copies and moving them around. This gives a realistic probability to seeing duplicate expressions, which some optimizations look for, which otherwise the fuzzer would have almost never reached. * Mutate function pieces after recombination, giving not only perfect duplicates but also near-duplicates. These operations take into account the type, but not the nesting and uniqueness of labels, so we fix that up afterwards (when something is broken, we replace it with something trivial).
* fix flipping in dataflow graph generation (#1732)Alon Zakai2018-11-083-107/+201
| | | For souper we need to flip some operations in DataFlow IR, since souper doesn't have any redundant ones. But we flipped not just left and right but also equal/not equal, which was wrong.
* Rename tableBase/memoryBase to __table_base/__memory_base (#1731)Sam Clegg2018-11-08151-408/+474
|
* Fix a merge-blocks fuzz bug (#1730)Alon Zakai2018-11-082-21/+134
| | | | | | | | | | | | | | | If a block has code after an unreachable element, it makes merging to an outer block tricky - the child block may be unreachable, but the parent have a return type, (block (result i32) .. (block (unreachable) (nop) ) ) It's ok to end an unreachable block with a nop, but not a typed one. To avoid this, if a child block has dce-able code, just ignore it.
* Fix a DataFlowOpts bug (#1729)Alon Zakai2018-11-072-0/+21
| | | | | | | We create some fake nodes for internal use, and were looking at one by mistake. This fixes that by * Creating a non-ambiguous fake node, a call (which represents an unknown value properly, unlike a zero which we had before). * Make DFO not rely on those values, if it knows a node is constant, apply those constant values. Found by the fuzzer.
* Fix a bug with (add (sub 0 X) Y) => (sub Y X) (#1727)Alon Zakai2018-11-072-0/+53
| | | | | We need to verify that the reordering is valid if there are side effects. Original bug report: https://groups.google.com/forum/?nomobile=true#!topic/emscripten-discuss/HIlGf8o2Ato
* add support for new call_indirect syntax ; fixes #1724 (#1725)Alon Zakai2018-11-054-0/+69
|
* Suppress the 'has StackIR' comment when printing StackIR (#1726)Daniel Wirtz2018-11-046-58/+58
| | | Follow-up to #1717
* Fix asm2wasm handling of HEAP8[x >> 2] (#1720)Alon Zakai2018-11-027-9/+78
| | | | | | fixes kripken/emscripten#1718 The way fastcomp emits compareExchange is a little odd, we just need to ignore the shift.
* Add pass to minify import and export names (#1719)Alon Zakai2018-11-012-0/+15026
| | | | | | | | | This new pass minifies import and export names, for example, this may minify (import "env" "longname" (func $internal)) to (import "env" "a" (func $internal)) By updating the JS that provides those imports/calls those exports, we can use the minified names properly. This can save a useful amount of space in the wasm and JS, see kripken/emscripten#7414
* Emit imports before defined things in text format (#1715)Alon Zakai2018-11-01186-255/+255
| | | | | That is the correct order in the text format, wabt errors otherwise. See AssemblyScript/assemblyscript#310
* Add Module#emitStackIR to the JS-API (#1717)Daniel Wirtz2018-10-312-0/+77
| | | Related to #1716 (comment)
* Expand asmConsts metadata to fit the shape of proxying async EM_ASMs (no ↵Jacob Gravelle2018-10-251-1/+1
| | | | actual support) (#1711)
* Support 4GB Memories (#1702)Alon Zakai2018-10-159-2/+34
| | | This fixes asm2wasm parsing of the max to allow 4GB, and also changes the internal Memory::kMaxValue values to reflect that. We used to use kMaxValue to also represent "no limit", so I split that out into kUnlimitedValue.
* Shared memory support for add memory import and set memory functions. (#1686)Nidin Vinayakan2018-10-117-9/+9
|
* No atomic float operations (#1693)Alon Zakai2018-10-051-1104/+110
| | | | | SafeHeap was emitting them, but it looks like they are invalid according to the wasm-threads spec. Fixes kripken/emscripten#7208
* Add initial/maximum table size parameters to C/JS API (#1687)Daniel Wirtz2018-09-284-7/+6
|
* More #1678 fixes (#1685)Alon Zakai2018-09-206-6/+100
| | | While debugging to fix the waterfall regressions I noticed that wasm-reduce regressed. We need to be more careful with visitFunction which now may visit an imported function - I found a few not-well-tested passes that also regressed that way.
* Unify imported and non-imported things (#1678)Alon Zakai2018-09-19251-801/+773
| | | | | | | | | | | | | | 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.
* Add debug information locations to the function prolog/epilog (#1674)Yury Delendik2018-09-179-6/+79
| | | | | | | The current patch: * Preserves the debug locations from function prolog and epilog * Preserves the debug locations of the nested blocks
* fix sign detection of a floating-point mod ; fixes kripken/emscripten#7123 ↵Alon Zakai2018-09-157-30/+150
| | | | (#1681)
* Note that calls to imports are not lightweight in inlining pass (#1673)Alon Zakai2018-09-121-2581/+2537
| | | | * call_import is not lightweight for inlining purposes - we had call but not callimport, which is even less light
* Misc tiny fuzz fixes (#1668)Alon Zakai2018-09-1215-25/+8
| | | | | | | | | | | | * show a proper error for an empty asm2wasm input * handle end of input in processExpressions in binary reading * memory segment sizes should be unsigned * validate input in wasm-ctor-eval * update tests
* check-in the test/spec suite instead of as submodule (#1677)Jay Phelps2018-09-1198-0/+22299
|
* Binary format local parsing fixes (#1664)Alon Zakai2018-09-1130-568/+568
| | | | | | * 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.
* [wasm2js] Fix base64 encoding (#1670)Yury Delendik2018-09-052-0/+51
| | | The static std::string base64Encode(std::vector<char> &data) { uses signed char in input data. The ((int)data[0]) converts it the signed int, making '\xFF' char into -1. The patch fixes casting.
* DeadArgumentElimination Pass (#1641)Alon Zakai2018-09-0519-1709/+1243
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This adds a pass to remove unnecessary call arguments in an LTO-like manner, that is: * If a parameter is not actually used in a function, we don't need to send anything, and can remove it from the function's declaration. Concretely, (func $a (param $x i32) ..no uses of $x.. ) (func $b (call $a (..)) ) => (func $a ..no uses of $x.. ) (func $b (call $a) ) And * If a parameter is only ever sent the same constant value, we can just set that constant value in the function (which then means that the values sent from the outside are no longer used, as in the previous point). Concretely, (func $a (param $x i32) ..may use $x.. ) (func $b (call $a (i32.const 1)) (call $a (i32.const 1)) ) => (func $a (local $x i32) (set_local $x (i32.const 1) ..may use $x.. ) (func $b (call $a) (call $a) ) How much this helps depends on the codebase obviously, but sometimes it is pretty useful. For example, it shrinks 0.72% on Unity and 0.37% on Mono. Note that those numbers include not just the optimization itself, but the other optimizations it then enables - in particular the second point from earlier leads to inlining a constant value, which often allows constant propagation, and also removing parameters may enable more duplicate function elimination, etc. - which explains how this can shrink Unity by almost 1%. Implementation is pretty straightforward, but there is some work to make the heavy part of the pass parallel, and a bunch of corner cases to avoid (can't change a function that is exported or in the table, etc.). Like the Inlining pass, there is both a standard and an "optimizing" version of this pass - the latter also optimizes the functions it changes, as like Inlining, it's useful to not need to re-run all function optimizations on the whole module.
* [wasm2js] Fix nested selects (#1671)Yury Delendik2018-09-052-0/+62
| | | | In wasmjs, the nested selects are trying to use the same temporary locals. The patch reserves temporaries "at right time" to avoid overriding the values.
* Loop Invariant Code Motion (#1658)Alon Zakai2018-09-042-0/+1069
| | | | | | | | | | | | | | | | | | | | | This adds an licm pass. Not that important for LLVM-originating code obviously, but for AssemblyScript and other non-LLVM compilers this might help a lot. Also when wasm has GC a bunch more non-LLVM languages may arrive that can benefit. The pass is mostly straightforward. I considered using the DataFlow IR since it's in SSA form, or the CFG IR, but in the end it's actually pretty convenient to use the main IR as it is - with explicit loops already present - plus LocalGraph which connects each get to the sets influencing it. Passed a bunch of fuzzing, and also the emscripten test suite at -O1 with licm added to the default passes (but I don't think it would make sense to run this by default, as LLVM doesn't need it). We limit code moved by this pass as follows: An increased code size on fuzz testcases (and, more rarely, on real inputs) can happen due to stuff like this: (loop (set_local $x (i32.const 1)) .. ) => (set_local $x (i32.const 1)) (loop .. ) For a const or a get_local, such an assignment to a local is both very cheap (a copy to another local may be optimized out later), and moving it out may prevent other optimizations (since we have no pass that tries to move code back in to a loop edit well, not by default, precompute-propagate etc. would do it, but are only run on high opt levels). So I made the pass not move such trivial code (sets/tees of consts or gets). However, the risk remains if code is moved out that is later reduced to a constant, so something like -Os --flatten --licm -Os may make sense.
* Change the Literal class's operator== to be bitwise (#1661)Alon Zakai2018-09-012-0/+58
| | | | | The change means that nan values will be compared bitwise when writing A == B, and so the float rule of a nan is different from itself would not apply. I think this is a safer default. In particular this PR fixes a fuzz bug in the rse pass, which placed Literals in a hash table, and due to nan != nan, an infinite loop... Also, looks like we really want a bitwise comparison pretty much everywhere anyhow, as can be seen in the diff here. Really the single place we need a floaty comparison is in the intepreter where we implement f32.eq etc., and there the code was already using the proper code path anyhow.
* BinaryenSetFunctionTable now accepts array of func names not funcs. (#1650)Jay Phelps2018-09-015-9/+24
| | | | | This allows using imports in the table. Fixes #1645
* Escape name section ids in binary format reading/writing to be WebAssembly ↵Yury Delendik2018-08-316-0/+47
| | | | spec compatible. (#1646)
* Remove replaced imports in LegalizeJSInterface (#1657)Sam Clegg2018-08-307-145/+127
| | | | This pass was replacing all the uses of certain imports but wasn't bothering to delete the old ones.
* Rename `wasm2asm` to `wasm2js`, emit ESM by default (#1642)Alex Crichton2018-08-3073-903/+2104
| | | | | | | | | | | | | | | | | | | | | | | | * Rename the `wasm2asm` tool to `wasm2js` This commit performs a relatively simple rename of the `wasm2asm` tool to `wasm2js`. The functionality of the tool doesn't change just yet but it's intended that we'll start generating an ES module instead of just an `asm.js` function soon. * wasm2js: Support `*.wasm` input files Previously `wasm2js` only supported `*.wast` files but to make it a bit easier to use in tooling pipelines this commit adds support for reading in a `*.wasm` file directly. Determining which parser to use depends on the input filename, where the binary parser is used with `*.wasm` files and the wast parser is used for all other files. * wasm2js: Emit ESM imports/exports by default This commit alters the default behavior of `wasm2js` to emit an ESM by default, either importing items from the environment or exporting. Items like initialization of memory are also handled here.
* Update tests after #1653 (#1656)Sam Clegg2018-08-301-6/+45
|
* wasm-emscripten-finalize: Don't allow duplicates in 'declares'/'invok… (#1655)Sam Clegg2018-08-292-0/+100
| | | | | Allowing duplicates here was causes emscripten to generate a JS object with duplicate keys.
* Improve getFallthrough (#1643)Alon Zakai2018-08-272-0/+138
| | | | | That method looks through tee_locals and other operations that receive a value and let it flow through them, like a block's final value, etc. It just handled a few such operations, with this PR all of them should be handled. Also refactor it out of the OptimizeInstructions pass as I think it may be useful for propagating returned constants.
* Souper integration + DataFlow optimizations (#1638)Alon Zakai2018-08-278-0/+13239
| | | | | | | | | Background: google/souper#323 This adds a --souperify pass, which emits Souper IR in text format. That can then be read by Souper which can emit superoptimization rules. We hope that eventually we can integrate those rules into Binaryen. How this works is we emit an internal "DataFlow IR", which is an SSA-based IR, and then write that out into Souper text. This also adds a --dfo pass, which stands for data-flow optimizations. A DataFlow IR is generated, like in souperify, and then performs some trivial optimizations using it. There are very few things that can do that our other optimizations can't already, but this is also good testing for the DataFlow IR, plus it is good preparation for using Souper's superoptimization output (which would also construct DataFlow IR, like here, but then do some matching on the Souper rules).
* Fix value flowing in remove-unused-brs (#1639)Alon Zakai2018-08-202-3/+100
| | | | | The fuzzer found a bug with flowing of values in that pass: when one arm of an if is none-typed, we can't flow a value through the other. Odd the fuzzer didn't find this earlier, as it's been a bug since the pass was written years ago, but in practice it seems you need a specific set of circumstances on the outside for it to be hit. The fix is to stop flowing a value in that case. Also, I realized after fixing it that the valueCanFlow global state variable is entirely unneeded. Removing it makes the pass significantly simpler: at all times, flows contains branches and values that might be flowing, and if the flow stops we remove them, etc. - we don't need an extra state variable to say if flowing is possible. So when we want to use the flows, we just check what is there (and then for a flowing branch we can remove it, and for a flowing value we can replace the branch with the value, etc., as in both cases they flow to the right place anyhow).
* Print Stack IR in proper .wat format (#1630)Alon Zakai2018-08-1410-647/+762
| | | This now makes --generate-stack-ir --print-stack-ir emit a fully valid .wat wasm file, in stacky format.
* wasm-ctor-eval improvements (#1631)Alon Zakai2018-08-0712-126/+14
| | | | | * When we eval a ctor, don't just nop the function body that no longer needs to be executed, also remove the export (as we report the ctor being evalled, and the outside will no longer call it). * Run the pass to remove unused global things. This can usually remove evalled ctors (unless something else happens to call them, which can't happen normally as LLVM wouldn't use a ctor in another place, but e.g. duplicate function merging might merge a ctor with another function).
* Stack IR (#1623)Alon Zakai2018-07-3084-767/+3332
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Fix source map entries offset when LEB is compressed. (#1628)Yury Delendik2018-07-258-21/+22
|
* Notice parse errors on number parsing in the text format (#1608)Loppin Vincent2018-07-243-2/+8
| | | | | | | * - Throw ParseException when istringstream failed to read a number. - Modify now invalid tests. * Add invalid_number.wast test