summaryrefslogtreecommitdiff
path: root/test/passes
Commit message (Collapse)AuthorAgeFilesLines
* Remove FunctionType (#2510)Thomas Lively2019-12-11149-4364/+3878
| | | | | | | | | | | | | | | | | Function signatures were previously redundantly stored on Function objects as well as on FunctionType objects. These two signature representations had to always be kept in sync, which was error-prone and needlessly complex. This PR takes advantage of the new ability of Type to represent multiple value types by consolidating function signatures as a pair of Types (params and results) stored on the Function object. Since there are no longer module-global named function types, significant changes had to be made to the printing and emitting of function types, as well as their parsing and manipulation in various passes. The C and JS APIs and their tests also had to be updated to remove named function types.
* Fix loop parent computation in DataFlow.Graph (#2522)Heejin Ahn2019-12-112-0/+43
| | | | | | This fixes the parent-child relationship computation in `DataFlow.Graph` when there is a loop. This wasn't discovered until now because this is used in Souperify and Souperify only runs after Flatten pass, which produces redundant blocks between inside and outside of a loop.
* Add a RoundTrip pass (#2516)Alon Zakai2019-12-092-0/+18
| | | | | | This pass writes and reads the module. This shows the effects of converting to and back from the binary format, and will be useful in testing dwarf debug support (where we'll need to see that writing and reading a module preserves debug info properly).
* Fix comparison of none and unreachable types (#2514)Heejin Ahn2019-12-092-538/+957
| | | | | | | | | | | | | | | | | | | Currently `none` and `unreachable` types are stored as the same empty `{}` in src/wasm/wasm-type.cpp. This makes `Type::operator<` incorrectly when given `none` and `unreachable`, because it expands both given types and lexicographically compare them, when both of the expanded vector will be empty. This was found by the fuzzer. This line in `Modder::visitExpression` tries to retrieve candidates of the same type. Because we can't really compare these two types, if you give `unreachable` as the key, candidates of `none` type can be returned. This generates incorrect code that ends up failing in validation in a very weird way. It was hard to generate a small testcase to trigger this part because it was found by generating fuzzed code from a random data file. But I guess this fix is pretty straightforward. Fixes #2512.
* Don't include `$` with names unless outputting to wat format (#2506)Sam Clegg2019-12-067-573/+573
| | | | | | | | | | | The `$` is not actually part of the name, its the marker that starts a name in the wat format. It can be confusing to see it show up when doing `cerr << name`, for example. This change has Print.cpp add the `$` which seem like the right place to do this. Plus it revealed a bunch of places where were not calling printName to escape all the names we were printing.
* Print only literal values when printing literals (#2469)Heejin Ahn2019-11-263-16/+12
| | | | | | | | | | | | | | | Current `<<` operator on `Literal` prints `[type].const` with it. But `[type].const` is rather an instruction than a literal itself, and printing it with the literals makes less sense when we later have literals whose type don't have `const` instructions (such as reference types). This patch - Makes `<<` operator on `Literal` print only its value - Makes wasm-shell's shell interface comply with the spec interpreter's printing format (`value : type`). - Prints wasm-shell's `[trap]` message to stderr These make all `fix_` routines for spec tests in check.py unnecessary.
* Remove FunctionType from Event (#2466)Thomas Lively2019-11-255-2222/+670
| | | | | | | | | This is the start of a larger refactoring to remove FunctionType entirely and store types and signatures directly on the entities that use them. This PR updates BrOnExn and Events to remove their use of FunctionType and makes the BinaryWriter traverse the module and collect types rather than using the global FunctionType list. While we are collecting types, we also sort them by frequency as an optimization. Remaining uses of FunctionType in Function, CallIndirect, and parsing will be removed in a future PR.
* Multivalue type creation and inspection (#2459)Thomas Lively2019-11-222-1394/+1796
| | | | | | | | | | | | | Adds the ability to create multivalue types from vectors of concrete value types. All types are transparently interned, so their representation is still a single uint32_t. Types can be extracted into vectors of their component parts, and all the single value types expand into vectors containing themselves. Multivalue types are not yet used in the IR, but their creation and inspection functionality is exposed and tested in the C and JS APIs. Also makes common type predicates methods of Type and improves the ergonomics of type printing.
* Add a pass to inline __original_main() into main() (#2461)Alon Zakai2019-11-212-0/+122
| | | | | | | | | | | | | | | | | | clang/llvm introduce __original_main as a workaround for the fact that main may have different signatures. A downside to that is that users get it in stack traces, which is confusing. In -O2 and above we normally inline __original_main anyhow, but as this is for debugging, non-optimized builds matter too, so add a pass for this. The implementation is trivial, just call doInling. However we must check some corner cases first. Bonus minor fixes to FindAllPointers, which unnecessarily created an object to get the class Id (which is not valid for all classes), and that it didn't take the input by reference properly, which meant we couldn't get the pointer to the function body's toplevel.
* Add a --strip-dwarf pass (#2454)Alon Zakai2019-11-192-0/+32
| | | | | | | | | | | | | This pass strips DWARF debug sections, but not other debug sections. This is useful when emitting source maps, as we do need the SourceMapURL section, but the DWARF sections are not longer necessary (and we've seen a testcase where they are massively large, so big the wasm can't even be loaded in a browser...). Also contains a trivial one-line fix in --extract-function which was necessary to create the testcase here: that pass extracts a function from a wasm file (like llvm-extract) but it didn't check if an export already existed for the function.
* Add PostAssemblyScript pass (#2407)Daniel Wirtz2019-11-194-0/+699
| | | | | Adds the AssemblyScript-specific passes post-assemblyscript and post-assemblyscript-finalize, eliminating redundant ARC-style retain/release patterns conservatively emitted by the compiler.
* Optimize away invoke_ calls where possible (#2442)Alon Zakai2019-11-192-3/+157
| | | | | | | | | | | | When we see invoke_ calls in emscripten-generated code, we know they call into JS just to do a try-catch for exceptions. If the target being called cannot throw, which we check in a whole-program manner, then we can simply skip the invoke. I confirmed that this fixes the regression in emscripten-core/emscripten#9817 (comment) (that is, with this optimization, upstream is around as fast as fastcomp). When we have native wasm exception handling, this can be extended to optimize that as well.
* When legalizing, optionally export the original function too with orig$X (#2427)Alon Zakai2019-11-112-0/+34
| | | | | The original is necessary if we want to pass it to wasm, where it will be called directly, without JS legalization. For example the JS dynamic loader in emscripten needs this, emscripten-core/emscripten#9562
* Fix catch parsing (#2428)Heejin Ahn2019-11-112-18/+22
| | | | | | | - When a catch body is a block, call its `finalize` function with the correct type - Don't create a block when there's one instruction in a catch body - Remove `makeCatch` from gen-s-parser.py; it's not necessary - Fix a test case that has a `catch` without `try`
* Add Stack IR optimization support for EH (#2425)Heejin Ahn2019-11-072-0/+0
|
* Improve type selection in fuzzer (#2424)Heejin Ahn2019-11-062-1131/+1771
| | | | | | | | | - Adds `items` function for `FeatureOptions` so we can get a vector of eligible types - Replaces hardcoded enumeration of MVP types with `getConcreteTypes`, which also adds v128 type to the list if SIMD is enabled - Removes `getType()` function; this does not seem to be used anywhere - Renames `vectorPick` with `pick` - Use the absolute path for d8 in the fuzzer
* OptimizeInstructions: Eq64 of 0 => Eqz64 (#2421)Alon Zakai2019-11-043-7/+40
| | | Fixes #2417
* Fix PostWalker traversal of push instruction (#2419)Heejin Ahn2019-11-042-0/+22
| | | PostWalker traversal should visit its value.
* Add EH support for DCE pass (#2415)Heejin Ahn2019-11-012-0/+65
| | | | Like an `If`, `Try` construct is reachable when either its try body or catch body is reachable. This adds support for that.
* Don't remove events used in instructions (#2412)Heejin Ahn2019-11-012-8/+48
| | | | | Previously RemoveUnusedModuleElements pass only preserved exported events and did not preserve events used in `throw` and `br_on_exn` instructions. This fixes it.
* Do not precompute SIMDLoad (#2409)Thomas Lively2019-10-302-1/+15
| | | This fixes a crash when programs containing load_splats are optimized.
* Add ModAsyncify* passes (#2404)Alon Zakai2019-10-238-0/+1329
| | | | | | | | | | | | | | | | | | | | | | | | | | | | These passes are meant to be run after Asyncify has been run, they modify the output. We can assume that we will always unwind if we reach an import, or that we will never unwind, etc. This is meant to help with lazy code loading, that is, the ability for an initially-downloaded wasm to not contain all the code, and if code not present there is called, we download all the rest and continue with that. That could work something like this: * The wasm is created. It contains calls to a special import for lazy code loading. * Asyncify is run on it. * The initially downloaded wasm is created by running --mod-asyncify-always-and-only-unwind: if the special import for lazy code loading is called, we will definitely unwind, and we won't rewind in this binary. * The lazily downloaded wasm is created by running --mod-asyncify-never-unwind: we will rewind into this binary, but no longer need support for unwinding. (Optionally, there could also be a third wasm, which has not had Asyncify run on it, and which we'd swap to for max speed.) These --mod-asyncify passes allow the optimizer to do a lot of work, especially for the initially downloaded wasm if we have lots of calls to the lazy code loading import. In that case the optimizer will see that those calls unwind, which means the code after them is not reached, potentially making lots of code dead and removable.
* Enable exnref instrumentation when EH is enabled (#2379)Heejin Ahn2019-10-111-1/+1
| | | | `exnref` is enabled by not reference type feature but exception handling feature. Sorry that I missed this in #2377.
* Don't instrument pops in InstrumentLocals (#2378)Heejin Ahn2019-10-102-13/+39
| | | | | `pop` is not a real instruction and automatically generated when reading binary and deleted when writing binary, so this does not work with instrumentation.
* Only add instrumentation to reftypes when the featureset supports it (#2377)Jacob Gravelle2019-10-101-2/+2
|
* Add support for reftypes in InstrumentLocals pass (#2375)Heejin Ahn2019-10-102-10/+84
| | | This adds support for anyref and exnref types in InstrumentLocals pass.
* Apply the sbrk/brk value at compile time (#2366)Alon Zakai2019-09-302-0/+95
| | | | | We've had an option to set the location of the sbrk ptr, but not the value. Applying the value as well is necessary for standalone wasm, as otherwise we set it in JS.
* SimplifyGlobals: Apply known constant values in linear traces (#2340)Alon Zakai2019-09-135-1/+460
| | | | | | | | | | | | | This optimizes stuff like (global.set $x (i32.const 123)) (global.get $x) into (global.set $x (i32.const 123)) (i32.const 123) This doesn't help much with LLVM output as it's rare to use globals (except for the stack pointer, and that's already well optimized), but it may help on general wasm. It can also help with Asyncify that does use globals extensively.
* Add asserts in Asyncify (#2338)Alon Zakai2019-09-132-0/+232
| | | | | With the optional asserts, we throw if we see an unwind begin in code that we thought could never unwind (say, because the user incorrectly blacklisted it). Helps with emscripten-core/emscripten#9389
* Properly handle fastcomp *wasm* safe heap (#2334)Alon Zakai2019-09-062-0/+1915
| | | | | Properly handle fastcomp wasm safe heap: emscripten_get_sbrk_ptr is an asm.js library function, which means it is inside the wasm after asm2wasm, and exported. Find it via the export.
* SafeHeap: Prepare for emscripten_get_sbrk_ptr (#2331)Alon Zakai2019-09-054-662/+4484
| | | | | | | Currently emscripten links the wasm, then links the JS, then computes the final static allocations and in particular the location of the sbrk ptr (i.e. the location in memory of the brk location). Emscripten then imports that into the asm.js or wasm as env.DYNAMICTOP_PTR. However, this didn't work in the wasm backend where we didn't have support for importing globals from JS, so we implement sbrk in JS. I am proposing that we change this model to allow us to write sbrk in C and compile it to wasm. To do so, that C code can import an extern C function, emscripten_get_sbrk_ptr(), which basically just returns that location. The PostEmscripten pass can even apply that value at compile time, so we avoid the function call, and end up in the optimal place, see #2325 and emscripten PRs will be opened once other stuff lands. However, the SafeHeap pass must be updated to handle this, or our CI will break in the middle. This PR fixes that, basically making it check if env.DYNAMICTOP_PTR exists, or if not then looking for env.emscripten_get_sbrk_ptr, so that it can handle both.
* Add an option for the PostEmscripten pass to set the sbrk ptr location ↵Alon Zakai2019-09-042-0/+13
| | | | | | | (which is called DYNAMICTOP_PTR in emscripten) (#2325) The assumption is that an import env.emscripten_get_sbrk_ptr exists, and we replace the value returned from there with a constant. (We can't do all this in wasm-emscripten-finalize, as it happens before the JS compiler runs, which can add more static allocations; we only know where the sbrk ptr is later in compilation.) This just replaces the import with a function returning the constant; inlining etc. can help more later. By setting this at compile time we can reduce code size and avoid importing it at runtime, which makes us more compatible with wasi (less special imports).
* Minify wasi imports and exports, and not just "env" (#2323)Alon Zakai2019-09-012-10/+15
| | | This makes the minification pass aware of "wasi_unstable" and "wasi" as well.
* Add atomic.fence instruction (#2307)Heejin Ahn2019-08-272-696/+1000
| | | | | | | This adds `atomic.fence` instruction: https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md#fence-operator This also fix bugs in `atomic.wait` and `atomic.notify` instructions in binaryen.js and adds tests for them.
* Add basic exception handling support (#2282)Heejin Ahn2019-08-132-0/+66
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This adds basic support for exception handling instructions, according to the spec: https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md This PR includes support for: - Binary reading/writing - Wast reading/writing - Stack IR - Validation - binaryen.js + C API - Few IR routines: branch-utils, type-updating, etc - Few passes: just enough to make `wasm-opt -O` pass - Tests This PR does not include support for many optimization passes, fuzzer, or interpreter. They will be follow-up PRs. Try-catch construct is modeled in Binaryen IR in a similar manner to that of if-else: each of try body and catch body will contain a block, which can be omitted if there is only a single instruction. This block will not be emitted in wast or binary, as in if-else. As in if-else, `class Try` contains two expressions each for try body and catch body, and `catch` is not modeled as an instruction. `exnref` value pushed by `catch` is get by `pop` instruction. `br_on_exn` is special: it returns different types of values when taken and not taken. We make `exnref`, the type `br_on_exn` pushes if not taken, as `br_on_exn`'s type.
* Duplicate Import Elimination (#2292)Alon Zakai2019-08-092-0/+31
| | | | | | | | | | | | | This is both an optimization and a workaround for the problem that emscripten-core/emscripten#7641 uncovered and had to be reverted because of. What's going on there is that wasm-emscripten-finalize turns emscripten_longjmp_jmpbuf into emscripten_longjmp (for some LLVM internal reason - there's a long comment in the source that I didn't fully follow). There are two such imports already, one for each name, and before that PR, we ended up with just one. After that PR, we end up with two. And with two, the minification of import names gets confused - we have two imports with the same name, and the code there ends up ignoring one of them. I'm not sure why that PR changed things - I guess the wasm-emscripten-finalize code looks at the name, and that PR changed what name appears? @sbc100 maybe #2285 is related? Anyhow, it's not trivial to make import minification code support two identical imports, but I don't think we should - we should avoid having such duplication anyhow. And we should add an assert that they don't exist (I'll open a PR for that later when it's possible). This fixes the duplication by adding a useful pass to remove duplicate imports (just functions, for now). Pretty simple, but we didn't do it yet. Even if there is a wasm-emscripten-finalize bug we need to fix with those duplicate imports, I think this pass is still a good thing to add. I confirmed that this fixes the issue caused by that PR.
* Remove trailing whitespaces after 'else' in stack IR (#2284)Heejin Ahn2019-08-061-5/+5
|
* Python3-ify check.py and auto_update_tests.py (#2270)Alon Zakai2019-07-312-1/+1
| | | | | I fixed flatten.bin.txt which seems to have just had some corrupted data, and I removed some fancy unicode from the spec comments tests, which I'm not sure it's important enough to figure out how to fix. Fixes #1691
* Fix stack pointer identification for wasm::ABI::getStackSpace(). (#2243)William Maddox2019-07-282-0/+817
| | | | | | | | * Fix stack pointer identification for wasm::ABI::getStackSpace(). Recent stack pointer simplification in Emscripten broke the --spill-pointers pass. This fix for #2229 restores this functionality by recognizing an alternative coding idiom in Emscripten-generated WASM code.
* Fix extra unreachable generation (#2266)Heejin Ahn2019-07-271-1/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Currently various expressions handle this differently, and now we consistently follow this rules: --- For all non-control-flow value-returning instructions, if a type of an expression is unreachable, we emit an unreachable and don't emit the instruction itself. If we don't emit an unreachable, instructions that follow can have validation failure in wasm binary format. For example: ``` [unreachable] (f32.add [unreachable] (i32.eqz [unreachable] (unreachable) ) ... ) ``` This is a valid prgram in binaryen IR, because the unreachable type propagates out of an expression, making both i32.eqz and f32.add unreachable. But in binary format, this becomes: ``` unreachable i32.eqz f32.add ;; validation failure; it expects f32 but takes an i32! ``` And here f32.add causes validation failure in wasm validation. So in this case we add an unreachable to prevent following instructions to consume the current value (here i32.eqz). In actual tests, I used `global.get` to an f32 global, which does not return a value, instead of `f32.add`, because `f32.add` itself will not be emitted if one of argument is unreachable. --- So the changes are: - For instructions that don't return a value, removes unreachable emitting code if it exists. - Add the unreachable emitting code for value-returning instructions if there isn't one. - Check for unreachability only once after emitting all children for atomic instructions. Currently only atomic instructions check unreachability after visiting each children and bail out right after, which is valid, but not consistent with others. - Don't emit an extra unreachable after a return (and return_call). I guess it is unnecessary.
* Fix unreachable prefix in instruction printing (#2265)Heejin Ahn2019-07-263-4/+4
| | | | | | | | | When a memory instruction's type is unreachable, i.e., one of its child expressions is unreachable, the instruction will be printed like `unreachable.load`, which is invalid text format. This prints unreachable prefix instruction types as `i32` to just make them pass the parser. It is OK because they are not reachable anyway. Also this removes printing of `?` in atomic.rmw instruction printing.
* Asyncify: whitelist and blacklist support (#2264)Alon Zakai2019-07-264-0/+610
| | | | | | | | | The blacklist means "functions here are to be ignored and not instrumented, we can assume they never unwind." The whitelist means "only these functions, and no others, can unwind." I had hoped such lists would not be necessary, since Asyncify's overhead is much smaller than the old Asyncify and Emterpreter, but as projects have noticed, the overhead to size and speed is still significant. The lists give power users a way to reduce any unnecessary overhead. A slightly tricky thing is escaping of names: we escape names from the names section (see #2261 #1646). The lists arrive in human-readable format, so we escape them before comparing to the internal escaped names. To enable that I refactored wasm-binary a little bit to provide the escaping logic, cc @yurydelendik If both lists are specified, an error is shown (since that is meaningless). If a name appears in a list that is not in the module, we show a warning, which will hopefully help people debug typos etc. I had hoped to make this an error, but the problem is that due to inlining etc. a single list will not always work for both unoptimized and optimized builds (a function may vanish when optimizing, due to duplicate function elimination or inlining). Fixes #2218.
* Finalize tail call support (#2246)Thomas Lively2019-07-236-2/+374
| | | | Adds tail call support to fuzzer and makes small changes to handle return calls in multiple utilities and passes. Makes larger changes to DAE and inlining passes to properly handle tail calls.
* SimplifyGlobals: Propagate constants in global initializers (#2238)Alon Zakai2019-07-201-6/+6
| | | | | | | | | | | (global $g1 (mut i32) (i32.const 42)) (global $g2 i32 (global.get $g1)) can be optimized to (global $g1 (mut i32) (i32.const 42)) (global $g2 i32 (i32.const 42)) even though $g1 is mutable - because it can't be mutated during module instantiation.
* Re-land #2235 with fixes (#2245)Thomas Lively2019-07-202-1/+47
| | | | #2242 had exposed the bug that the `Trapper` pass was defining `walkFunction` when it should have been defining `doWalkFunction`.
* Revert "Remove bulk memory instructions refering to active segments (#2235)" ↵Thomas Lively2019-07-192-47/+1
| | | | | (#2244) This reverts commit 72c52ea7d4eb61b95cf8a5164947cb760fe42e9c, which was causing test failures after it merged.
* Remove bulk memory instructions refering to active segments (#2235)Thomas Lively2019-07-192-1/+47
| | | | This prevents those instructions from becoming invalid due to memory packing optimizations and is also a code size win. Fixes #2227.
* SimplifyGlobals: Constant-propagate constant values of immutable globals (#2234)Alon Zakai2019-07-182-0/+89
|
* Bysyncify => Asyncify (#2226)Alon Zakai2019-07-1510-1009/+1009
| | | | | | | After some discussion this seems like a less confusing name: what the pass does is "asyncify" code, after all. The one downside is the name overlaps with the old emscripten "Asyncify" utility, which we'll need to clarify in the docs there. This keeps the old --bysyncify flag around for now, which is helpful for avoiding temporary breakage on CI as we move the emscripten side as well.
* Optimize select fallthrough values (#2220)Alon Zakai2019-07-112-0/+20
| | | This became noticeable after #2216 which led to some eqz eqz pairs in the test suite.