| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
| |
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.
|
|
|
|
| |
`strpbrk` segfaults when `name.str` is nullptr, so check first.
|
|
|
|
| |
* 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
|
|
|
|
|
| |
Not at all sure why we're seeing any there, but it's easy enough to
handle that we might as well.
|
|
|
| |
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.
|
|
|
|
| |
do it properly later (#1744)
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
This writes the data section into a file suitable for use with emscripten's
--memory-init-file flag
|
|
|
| |
Use c++11 auto, iterators, etc.
|
|
|
| |
Necessary for simd, as we add a type with alignment >8. We were just broken on that before this PR.
|
|
|
|
|
|
| |
* 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).
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
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
|
|
|
|
|
| |
Not being able to evaluate a ctor is different to that ctor
being absent. This is masked a bug in emscripten where we
were spelling the names of the ctors wrong on the command line.
|
| |
|
|
|
| |
Follow-up to #1717
|
|
|
|
|
|
| |
fixes kripken/emscripten#1718
The way fastcomp emits compareExchange is a little odd, we just need to ignore the shift.
|
|
|
|
|
| |
This was causing a deadlock while destroying the thread pool.
|
|
|
|
|
|
|
|
|
| |
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
|
|
|
|
|
| |
That is the correct order in the text format, wabt errors otherwise.
See AssemblyScript/assemblyscript#310
|
|
|
| |
Related to #1716 (comment)
|
| |
|
|
|
|
| |
actual support) (#1711)
|
| |
|
|
|
| |
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.
|
|
|
|
| |
(#1696)
|
| |
|
| |
|
|
|
|
|
| |
SafeHeap was emitting them, but it looks like they are invalid according to the wasm-threads spec.
Fixes kripken/emscripten#7208
|
| |
|
|
|
| |
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.
|
|
|
| |
Fixes the 3 regressions mentioned in a comment on #1678
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
The current patch:
* Preserves the debug locations from function prolog and epilog
* Preserves the debug locations of the nested blocks
|
|
|
|
| |
(#1681)
|
|
|
|
| |
* call_import is not lightweight for inlining purposes - we had call but not callimport, which is even less light
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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
|
|
|
| |
From #1665 (a fuzz bug noticed they were not handled in stack.h).
|
|
|
|
|
| |
We need to check not to read past the length of the string.
From #1665
|
|
|
|
|
|
| |
* 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.
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
This allows using imports in the table.
Fixes #1645
|
|
|
|
|
| |
We're about to rewrite both names anyway.
This fixes LLVM's c++ invokes, which get escaped to not match as of
PR #1646
|