summaryrefslogtreecommitdiff
path: root/src/passes/SimplifyLocals.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Rename indexType -> addressType. NFC (#7060)Sam Clegg2024-11-071-3/+3
| | | See https://github.com/WebAssembly/memory64/pull/92
* [Exceptions] Finish interpreter + optimizer support for try_table. (#6814)Sébastien Doeraene2024-08-201-3/+3
| | | | | | * Add interpreter support for exnref values. * Fix optimization passes to support try_table. * Enable the interpreter (but not in V8, see code) on exceptions.
* NonNullable => !Defaultable in SimplifyLocals (#6070)Alon Zakai2023-11-011-2/+4
| | | We handled references but not tuples in one place.
* LinearExecutionTraversal: Add an option to connect adjacent code, use in ↵Alon Zakai2023-08-081-0/+5
| | | | | | | | | | | SimplifyLocals (#5860) This addresses most of the minor regression from the correctness fix in #5857. That PR makes us consider calls as branching, but in some cases it is ok to ignore that branching (see the comment in the code here), which this PR allows as an option. This undoes one test change from that PR, showing it undoes the regression for SimplifyLocals. More tests are added to cover this specifically as well.
* Fix LinearExecutionWalker on calls (#5857)Alon Zakai2023-08-071-3/+4
| | | | | | | | | | | | | | Calls were simply not handled there, so we could think we were still in the same basic block when we were not, affecting various passes (but somehow this went unnoticed until the TNHOracle #5850 ran on some particular Java code). One existing test was affected, and two new tests are added: one for TNHOracle where I detected this, and one in OptimizeCasts which is perhaps a simpler way to see the problem. All the cases but the TNH one, however, do not need this fix for correctness since they actually don't care if a call would throw. As a TODO, we should find a way to undo this minor regression. The regression only affects builds with EH enabled, though, so most users should be unaffected even in the interm.
* SimplifyLocals: Refinalize after removing redundant tees (#5830)Alon Zakai2023-07-211-0/+3
|
* Switch from `typedef` to `using` in C++ code. NFC (#5258)Sam Clegg2022-11-151-1/+1
| | | | This is more modern and (IMHO) easier to read than that old C typedef syntax.
* SimplifyLocals: Fix handling of subtyping (#5210)Alon Zakai2022-11-021-16/+20
| | | | | | | We just checked if the new type we prefer (when switching a local to a more refined one in #5194) is different than the old type. But that check at the end must check it is a subtype as well. Diff without whitespace is smaller.
* [Wasm GC] SimplifyLocals: Switch local.get to use a more refined type when ↵Alon Zakai2022-11-011-16/+44
| | | | | | | | | | | | | | | possible (#5194) (local.set $refined (cast (local.get $plain))) .. .. (local.get $plain) .. ;; we can change this to read from $refined By using the more refined type we may be able to eliminate casts later. To do this, look at the fallthrough value (so we can look through a cast or a block value - this is the reason for the small wasm2js improvements in tests), and also extend the code that picks which local index to read to look at types (previously we just ignored any pairs of locals with different types).
* Refactor interaction between Pass and PassRunner (#5093)Thomas Lively2022-09-301-2/+3
| | | | | | | | | | | | | | Previously only WalkerPasses had access to the `getPassRunner` and `getPassOptions` methods. Move those methods to `Pass` so all passes can use them. As a result, the `PassRunner` passed to `Pass::run` and `Pass::runOnFunction` is no longer necessary, so remove it. Also update `Pass::create` to return a unique_ptr, which is more efficient than having it return a raw pointer only to have the `PassRunner` wrap that raw pointer in a `unique_ptr`. Delete the unused template `PassRunner::getLast()`, which looks like it was intended to enable retrieving previous analyses and has been in the code base since 2015 but is not implemented anywhere.
* [Wasm GC] Support non-nullable locals in the "1a" form (#4959)Alon Zakai2022-08-311-46/+45
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | An overview of this is in the README in the diff here (conveniently, it is near the top of the diff). Basically, we fix up nn locals after each pass, by default. This keeps things easy to reason about - what validates is what is valid wasm - but there are some minor nuances as mentioned there, in particular, we ignore nameless blocks (which are commonly added by various passes; ignoring them means we can keep more locals non-nullable). The key addition here is LocalStructuralDominance which checks which local indexes have the "structural dominance" property of 1a, that is, that each get has a set in its block or an outer block that precedes it. I optimized that function quite a lot to reduce the overhead of running that logic after each pass. The overhead is something like 2% on J2Wasm and 0% on Dart (0%, because in this mode we shrink code size, so there is less work actually, and it balances out). Since we run fixups after each pass, this PR removes logic to manually call the fixup code from various places we used to call it (like eh-utils and various passes). Various passes are now marked as requiresNonNullableLocalFixups => false. That lets us skip running the fixups after them, which we normally do automatically. This helps avoid overhead. Most passes still need the fixups, though - any pass that adds a local, or a named block, or moves code around, likely does. This removes a hack in SimplifyLocals that is no longer needed. Before we worked to avoid moving a set into a try, as it might not validate. Now, we just do it and let fixups happen automatically if they need to: in the common code they probably don't, so the extra complexity seems not worth it. Also removes a hack from StackIR. That hack tried to avoid roundtrip adding a nondefaultable local. But we have the logic to fix that up now, and opts will likely keep it non-nullable as well. Various tests end up updated here because now a local can be non-nullable - previous fixups are no longer needed. Note that this doesn't remove the gc-nn-locals feature. That has been useful for testing, and may still be useful in the future - it basically just allows nn locals in all positions (that can't read the null default value at the entry). We can consider removing it separately. Fixes #4824
* SimplifyLocals: ReFinalize when needed (#4878)Alon Zakai2022-08-091-0/+25
|
* [WasmGC] Fix try-catch and non-nullable local sets in values in ↵Alon Zakai2022-05-311-5/+17
| | | | | | | | | SimplifyLocals (#4705) Followup to #4703, this also handles the case where there is a non- nullable local.set in the value of a nullable one, which we also cannot optimize. Fixes #4702
* [WasmGC] Fix non-nullable locals and try-catch in SimplifyLocals (#4703)Alon Zakai2022-05-311-3/+38
| | | | | | | Binaryen will not change dominance in SimplifyLocals, however, the current spec's notion of dominance is simpler than ours, and we must not optimize certain cases in order to still validate. See details in the comment and test. Helps #4702
* [EH] Support try-delegate in EffectAnalyzer (#4368)Heejin Ahn2021-12-061-1/+1
| | | | | | | | | | | | | | | | This adds support for try-delegate in `EffectAnalyzer`. Without this support, the expresion below has been incorrectly classified as "cannot throw", because the previous code considered everything inside `try`-`catch_all` as "cannot throw". This is not the case when there is a `delegate` that can bypass the `catch_all`. ```wasm try $l0 try try throw $e delegate $l0 catch_all end end
* Modernize code to C++17 (#3104)Max Graey2021-11-221-12/+10
|
* Use the new module version of EffectAnalyzer (#4116)Alon Zakai2021-08-311-1/+1
| | | | | | | | | | | This finishes the refactoring started in #4115 by doing the same change to pass a Module into EffectAnalyzer instead of features. To do so this refactors the fallthrough API and a few other small things. After those changes, this PR removes the old feature constructor of EffectAnalyzer entirely. This requires a small breaking change in the C API, changing BinaryenExpressionGetSideEffects's feature param to a module. That makes this change not NFC, but otherwise it is.
* Add a Module parameter to EffectAnalyzer. NFC (#4115)Alon Zakai2021-08-311-12/+10
| | | | | | | | | | | | | Knowing the module will allow us to do more analysis in the effect analyzer. For now, this just refactors the code to allow providing a module instead of features, and to infer the features from the module. This actually shortens the code in most places which is nice (just pass module instead of module->features). This modifies basically all callers to use the new module form, except for the fallthrough logic. That would require some more refactoring, so to keep this PR reasonably small that is not yet done.
* [Wasm GC] Fix LinearExecutionWalker (#3954)Alon Zakai2021-06-291-3/+5
| | | | | | | | | | That traversal did not mention BrOn, which led to it doing incorrect work in SimplifyLocals. Also add assertions at the end, that aim to prevent future issues. The rest of the fix is to make SimplifyLocals not assume that things are a Switch if they are not an If/Block/etc., so that we don't crash on a BrOn.
* Refactor LinearExecutionWalker to a separate file. NFC (#3956)Alon Zakai2021-06-281-0/+1
|
* Remove exnref and br_on_exn (#3505)Heejin Ahn2021-01-221-4/+0
| | | This removes `exnref` type and `br_on_exn` instruction.
* Basic EH instrucion support for the new spec (#3487)Heejin Ahn2021-01-151-2/+2
| | | | | | | | | | | | | | | | | | | | This updates `try`-`catch`-`catch_all` and `rethrow` instructions to match the new spec. `delegate` is not included. Now `Try` contains not a single `catchBody` expression but a vector of catch bodies and events. This updates most existing routines, optimizations, and tests modulo the interpreter and the CFG traversal. Because the interpreter has not been updated yet, the EH spec test is temporarily disabled in check.py. Also, because the CFG traversal for EH is not yet updated, several EH tests in `rse_all-features.wast`, which uses CFG traversal, are temporarily commented out. Also added a few more tests in existing EH test functions in test/passes. In the previous spec, `catch` was catching all exceptions so it was assumed that anything `try` body throws is caught by its `catch`, but now we can assume the same only if there is a `catch_all`. Newly added tests test cases when there is a `catch_all` and cases there are only `catch`es separately.
* SimplifyLocals fuzz fix: Don't be confused by subtype assigns. (#3267)Alon Zakai2020-10-211-4/+11
| | | | | | | | We checked if the type matches when deciding if two locals are equivalent, but if the type didn't match, we forgot to reset any previously equivalent things. So we thought something was equivalent when it wasn't, see the reduced testcase. Fixes #3266
* Avoid wasted work when there are no locals (#3060)Max Graey2020-08-241-0/+3
| | | Adds early returns to local optimizations passes in cases where there are no locals to optimize.
* Prevent calls from sinking into 'try' (#2899)Heejin Ahn2020-06-071-0/+14
| | | | Expressions that may throw cannot be sinked into 'try'. At the start of 'try', we drop all sinkables that may throw.
* Prevent pops from sinking in SimplifyLocals (#2885)Heejin Ahn2020-06-031-0/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This prevents `exnref.pop`s from being sinked and separated from `catch`. For example, ```wast (try (do) (catch (local.set $0 (exnref.pop)) (call $foo (i32.const 3) (local.get $0) ) ) ) ``` Here, if we sink `exnref.pop` to remove `local.set $0` and `local.get $0`, it becomes this: ```wast (try (do) (catch (nop) (call $foo (i32.const 3) (exnref.pop) ) ) ) ``` This move was possible because `i32.const 3` does not have any side effects. But this is incorrect because now `exnref.pop` does not follow right after `catch`. To prevent this, this patch checks this case in `canSink` in SimplifyLocals. When we encountered a similar case in CodeFolding, we prevented every expression that contains `Pop` anywhere in it from being moved, which was too conservative. This adds `danglingPop` property in `EffectAnalyzer`, so that only pops that are not enclosed within a `catch` count as 'dangling pops` and we only prevent those pops from being moved or sinked.
* Add EH support for SimplifyLocals (#2858)Heejin Ahn2020-05-191-4/+6
| | | | | | | - `br_on_exn`'s target block cannot be optimized to have a separate return value. This handles that in `SimplifyLocals`. - `br_on_exn` and `rethrow` can trap (when the arg is null). This handles that in `EffectAnalyzer`. - Fix a few nits
* Add EH support for EffectAnalyzer (#2631)Heejin Ahn2020-02-031-9/+16
| | | | | | | | | | | | | | | | | | | | This adds EH support to `EffectAnalyzer`. Before `throw` and `rethrow` conservatively set property. Now `EffectAnalyzer` has a new property `throws` to represent an expression that can throw, and expression that can throw sets `throws` correctly. When EH is enabled, any calls can throw too, so we cannot reorder them with another expression with any side effects, meaning all calls should be treated in the same way as branches when evaluating `invalidate`. This prevents many reorderings, so this patch sets `throws` for calls only when the exception handling features is enabled. This is also why I passed `--disable-exception-handling` to `wasm2js` tests. Most of code changes outside of `EffectAnalyzer` class was made in order to pass `FeatureSet` to it. `throws` isn't always set whenever an expression contains a throwable instruction. When an throwable instruction is within an inner try, it will be caught by the corresponding inner catch, so it does not set `throws`.
* [NFC] Enforce use of `Type::` on type names (#2434)Thomas Lively2020-01-071-17/+19
|
* Add support for reference types proposal (#2451)Heejin Ahn2019-12-301-2/+4
| | | | | | | | | | | | This adds support for the reference type proposal. This includes support for all reference types (`anyref`, `funcref`(=`anyfunc`), and `nullref`) and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and new typed `select`. This also adds subtype relationship support between reference types. This does not include table instructions yet. This also does not include wasm2js support. Fixes #2444 and fixes #2447.
* Make local.tee's type its local's type (#2511)Heejin Ahn2019-12-121-4/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | According to the current spec, `local.tee`'s return type should be the same as its local's type. (Discussions on whether we should change this rule is going on in WebAssembly/reference-types#55, but here I will assume this spec does not change. If this changes, we should change many parts of Binaryen transformation anyway...) But currently in Binaryen `local.tee`'s type is computed from its value's type. This didn't make any difference in the MVP, but after we have subtype relationship in #2451, this can become a problem. For example: ``` (func $test (result funcref) (local $0 anyref) (local.tee $0 (ref.func $test) ) ) ``` This shouldn't validate in the spec, but this will pass Binaryen validation with the current `local.tee` implementation. This makes `local.tee`'s type computed from the local's type, and makes `LocalSet::makeTee` get a type parameter, to which we should pass the its corresponding local's type. We don't embed the local type in the class `LocalSet` because it may increase memory size. This also fixes the type of `local.get` to be the local type where `local.get` and `local.set` pair is created from `local.tee`.
* Reflect instruction renaming in code (#2128)Heejin Ahn2019-05-211-49/+49
| | | | | | | | | | | | | | | | | | | | | | | | | | | | - Reflected new renamed instruction names in code and tests: - `get_local` -> `local.get` - `set_local` -> `local.set` - `tee_local` -> `local.tee` - `get_global` -> `global.get` - `set_global` -> `global.set` - `current_memory` -> `memory.size` - `grow_memory` -> `memory.grow` - Removed APIs related to old instruction names in Binaryen.js and added APIs with new names if they are missing. - Renamed `typedef SortedVector LocalSet` to `SetsOfLocals` to prevent name clashes. - Resolved several TODO renaming items in wasm-binary.h: - `TableSwitch` -> `BrTable` - `I32ConvertI64` -> `I32WrapI64` - `I64STruncI32` -> `I64SExtendI32` - `I64UTruncI32` -> `I64UExtendI32` - `F32ConvertF64` -> `F32DemoteI64` - `F64ConvertF32` -> `F64PromoteF32` - Renamed `BinaryenGetFeatures` and `BinaryenSetFeatures` to `BinaryenModuleGetFeatures` and `BinaryenModuleSetFeatures` for consistency.
* clang-tidy braces changes (#2075)Alon Zakai2019-05-011-10/+20
| | | Applies the changes in #2065, and temprarily disables the hook since it's too slow to run on a change this large. We should re-enable it in a later commit.
* Properly handle optimizing out a set from inside the value of another set in ↵Alon Zakai2019-04-291-3/+56
| | | | | | | SimplifyLocals (#2064) Details in lengthy comment in the source. Fixes #2063
* Apply format changes from #2048 (#2059)Alon Zakai2019-04-261-90/+170
| | | Mass change to apply clang-format to everything. We are applying this in a PR by me so the (git) blame is all mine ;) but @aheejin did all the work to get clang-format set up and all the manual work to tidy up some things to make the output nicer in #2048
* Optimize added constants with propagation only if we see we will remove all ↵Alon Zakai2019-03-061-25/+3
| | | | uses of the original add, as otherwise we may just be adding work (both an offset, and an add). Refactor local-utils.h, and make UnneededSetRemover also check for side effects, so it cleanly removes all traces of unneeded sets.
* SmallVector (#1912)Alon Zakai2019-02-251-1/+1
| | | | | Trying to refactor the code to be simpler and less redundant, I ran into some perf issues that it seems like a small vector, with fixed-size storage and optional additional storage as needed, might help with. This implements that class and uses it in a few places. This seems to help, I see some 1-2% fewer instructions and cycles in `perf stat`, but it's hard to tell if it really makes a noticeable difference.
* Massive renaming (#1855)Thomas Lively2019-01-071-28/+28
| | | | | | Automated renaming according to https://github.com/WebAssembly/spec/issues/884#issuecomment-426433329.
* Properly optimize loop values (#1800)Alon Zakai2018-12-051-30/+42
| | | Remove the existing hack, and optimize them just like we do for ifs and blocks. This is now able to handle a few more cases than before.
* Speculate in simplify-locals that it is worth turning an if intoAlon Zakai (kripken)2018-12-041-27/+95
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | an if-else. If an if sets a local, (if (..condition..) (set_local $x (..value..)) ) we can turn it into (set_local $x (if (..condition..) (..value..) (get_local $x) ) ) This increases code size and adds a branch in the if, but allows the set to be optimized into a tee or optimized out entirely. In the worst case, other optimizations can break up an if with a copy in one of its arms later. Includes a determinism fix for EquivalentSets, which this patch triggered.
* Switch optimizations in remove-unused-brs (#1753)Alon Zakai2018-11-201-2/+3
| | | | | | * Switch optimizations in remove-unused-brs: thread switch jumps, and turn a switch with all identical targets into a br * refinalize in interm operations in remove-unused-brs, as we can be confused by it
* Improve local-cse (#1594)Alon Zakai2018-06-081-1/+1
| | | | | This makes it much more effective, by rewriting it to depend on flatten. In flattened IR, it is very simple to check if an expression is equivalent to one already available for use in a local, and use that one instead, basically we just track values in locals. Helps with #1521
* Fix optimizing equivalent locals bug introduced in #1540 (#1556)Alon Zakai2018-05-171-4/+2
| | | Don't skip through flowing tee values, just drop the current outermost which we find is redundant. the child tees may still be necessary.
* Optimize equivalent locals (#1540)Alon Zakai2018-05-101-72/+205
| | | | | | | | | If locals are known to contain the same value, we can * Pick which local to use for a get_local of any of them. Makes sense to prefer the most common, to increase the chance of one dropping to zero uses. * Remove copies between a local and one that we know contains the same value. This is a consistent win, small though, around 0.1-0.2%.
* Fix some fuzz bugs (#1528)Alon Zakai2018-05-011-15/+28
| | | | | * remove-unused-brs: handle an if declared as returning a value despite having an unreachable condition * simplify-locals: don't work on loops while the main pass is making changes, as set_locals are being tracked and modified.
* Generate loop return values in optimizer (#1527)Alon Zakai2018-05-011-0/+24
|
* More simplify-locals opts (#1526)Alon Zakai2018-05-011-22/+63
| | | | | | * Use an if return value when one side is unreachable. * Undo an if return value if we can use a br_if instead
* --simplify-locals-nonesting (#1525)Alon Zakai2018-04-301-57/+96
| | | | | Add a version of simplify-locals which does not create nesting. This keeps the IR flat (in the sense of --flatten). Also refactor simpify-locals to be a template, so the various modes are all template parameters.
* notation change: AST => IR (#1245)Alon Zakai2017-10-241-4/+4
| | | The IR is indeed a tree, but not an "abstract syntax tree" since there is no language for which it is the syntax (except in the most trivial and meaningless sense).
* fix simplify-locals bug where we create a br_if value, which is dangerous if ↵Alon Zakai2017-10-111-0/+46
| | | | we are moving code out of the br_if's condition - the value executes before (#1213)