summaryrefslogtreecommitdiff
path: root/src/passes/MergeBlocks.cpp
Commit message (Collapse)AuthorAgeFilesLines
* [Wasm EH] Optimize away _ref from try_table catches when unused (#6996)Alon Zakai2024-10-141-4/+52
| | | | | | | | | | | | | If we have (drop (block $b (result exnref) (try_table (catch_all_ref $b) then we don't really need to send the ref: it is dropped, so we can just replace catch_all_ref with catch_all and then remove the drop and the block value. MergeBlocks already had logic to remove block values, so it is the natural place to add this.
* ReFinalize in MergeBlocks so we can optimize unreachable instructions too ↵Alon Zakai2024-10-101-25/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | (#6994) In #6984 we optimized dropped blocks even if they had unreachable code. In #6988 that part was reverted, and blocks with unreachable code were ignored once more. However, I realized that the check was not actually for unreachable code, but for having an unreachable child, so it would miss things like this: (block (block .. (br $somewhere) ;; unreachable type, but no unreachable code ) ) But it is useful to merge such blocks: we don't need the inner block here. To fix this, just run ReFinalize if we change anything, which will propagate unreachability as needed. I think MergeBlocks was written before we had that utility, so it didn't use it... This is not only useful for itself but will unblock an EH optimization in a later PR, that has code in this form. It also simplifies the code by removing the hasUnreachableChild checks.
* Fix a fuzz issue with #6984 (#6988)Alon Zakai2024-10-071-14/+13
| | | | | | | | | | | | | | When I refactored the optimizeDroppedBlock logic in #6982, I didn't move the unreachability check with that code, which was wrong. When that function was called from another place in #6984, the fuzzer found an issue. Diff without whitespace is smaller. This reverts almost all the test updates from #6984 - those changes were on blocks with unreachable children. The change was safe on them, but in general removing a block value in the presence of unreachable code is tricky, so it's best to avoid it. The testcase is a little bizarre, but it's the one the fuzzer found and I can't find a way to generate a better one (other than to reduce it, which I did).
* MergeBlocks: Optimize all dropped blocks (#6984)Alon Zakai2024-10-041-0/+9
| | | | | | Just call optimizeDroppedBlock from visitDrop to handle that. Followup to #6982. This optimizes the new testcase added there. Some older tests also improve.
* [NFC] Refactor out the dropped-block optimization code in MergeBlocks (#6982)Alon Zakai2024-10-031-30/+46
| | | | | | | | This just moves the code out into a function. A later PR will use it in another place. Add a test that shows the motivation for that later PR: we fail to optimize away a block return value at the top level of a function. Fixing that will involve calling the new function here from another place.
* Use a SmallVector in MergeBlocks [NFC] (#5594)Alon Zakai2023-03-211-4/+9
| | | | | | | | This makes the pass 2-3% faster in some measurements I did locally. Noticed when profiling for #5561 (comment) Helps #4165
* Refactor interaction between Pass and PassRunner (#5093)Thomas Lively2022-09-301-1/+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.
* MergeBlocks: Rewrite to use a generic algorithm (#4323)Alon Zakai2021-11-121-54/+135
| | | | | | | | | | | | | | | | | | | | | Before this we had special logic for various call types. This replaces all that with a single general code path, which unifies everything except for control flow constructs (which remain as before, handled in a special way for each of them). The algorithm is simple and direct, basically it goes through the children and when it finds a block, it sees if it can move the block's contents outside of the parent. While doing so it takes into account effects and so forth. To make this easy, a random-access API is added to ChildIterator. Diff without whitespace makes the existing test updates a lot simpler. Note that this is not NFC as the old algorithm had some quirks like not taking into account effects when there were more than 2 children; the new code is uniform in how it handles things. This ends up removing 19% of all blocks in j2wasm, which reduces 1% of total code size.
* MergeBlocks: optimize If conditions (#4260)Alon Zakai2021-10-191-0/+5
| | | | | Code in the If condition can be moved out to before the if. Existing test updates are 99% whitespace.
* MergeBlocks: Allow side effects in a ternary's first element (#4238)Alon Zakai2021-10-131-6/+2
| | | | | | | | | | | Side effects in the first element are always ok there, as they are not moved across anything else: they happen before their parent both before and after the opt. The pass just left ternary as a TODO, so do at least one part of that now (we can do the rest as well, with some care). This is fairly useful on array.set which has 3 operands, and the first often has interesting things in it.
* [NFC] Add a comment in MergeBlocks about subtyping (#4142)Alon Zakai2021-09-101-2/+8
| | | Followup to #4137
* Refactor MergeBlocks to use iteration; adds Wasm GC support (#4137)Alon Zakai2021-09-091-30/+22
| | | | | | | | | MergeBlocks was written a very long time ago, before the iteration API, so it had a bunch of hardcoded things for specific instructions. In particular, that did not handle GC. This does a small refactoring to use iteration. The refactoring is NFC, but while doing so it adds support for new relevant instructions, including wasm GC.
* Add a Module parameter to EffectAnalyzer. NFC (#4115)Alon Zakai2021-08-311-16/+14
| | | | | | | | | | | | | 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 MergeBlocks on BrOn (#3702)Alon Zakai2021-03-181-25/+25
| | | | | | | | | | | The pass was only aware of Break and Switch. Refactor it to use the generic code, so that we can first handle Break, and then if anything remains, note a problem was found. The same path can handle a Switch which we handled before and also a BrOn etc. git diff is not that useful after the refactoring sadly, but basically this just moves the Break code and the Drop code, then adds the BranchUtils::operateOn stuff after them (and we switch to a unified visitor so that we get called for all expressions).
* Remove exnref and br_on_exn (#3505)Heejin Ahn2021-01-221-7/+0
| | | This removes `exnref` type and `br_on_exn` instruction.
* Basic EH instrucion support for the new spec (#3487)Heejin Ahn2021-01-151-2/+0
| | | | | | | | | | | | | | | | | | | | 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.
* [TypedFunctionReferences] Implement call_ref (#3396)Alon Zakai2020-11-241-1/+5
| | | | | | | | Includes minimal support in various passes. Also includes actual optimization work in Directize, which was easy to add. Almost has fuzzer support, but the actual makeCallRef is just a stub so far. Includes s-parser support for parsing typed function references types.
* Optimize MergeBlocks by caching branch results (#3102)Alon Zakai2020-09-031-7/+21
| | | | | | | | | | | BranchSeekerCache caches the set of branches in a node + its children, and helps compute new results by looking in the cache and using data for the children. This avoids quadratic time in the common case of a post-walk on a tower of nested blocks which is common in a switch. Fixes #3090 . On the testcase there this pass goes from over a minute to less than a second.
* Add EH support in MergeBlocks (#2848)Heejin Ahn2020-05-131-1/+22
| | | | | | | This adds support for `throw`, `rethrow`, and `br_on_exn` in MergeBlocks. While unrelated instructions within blocks can be hoisted as in other instructions, `br_on_exn` requires a special handling in `ProblemFinder`, because unlike `br_if`, its `exnref` argument itself cannot be moved out of `br_on_exn`.
* Add EH support for EffectAnalyzer (#2631)Heejin Ahn2020-02-031-10/+17
| | | | | | | | | | | | | | | | | | | | 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-5/+5
|
* Remove 'none' type as a branch target in ReFinalize (#2492)Alon Zakai2019-12-041-2/+2
| | | | | | | | | | | | | | | | | That was needed for super-old wasm type system, where we allowed (block $x (br_if $x (unreachable) (nop) ) ) That is, we differentiated "taken" branches from "named" ones (just referred to by name, but not actually taken as it's in unreachable code). We don't need to differentiate those any more. Remove the ReFinalize code that considered it, and also remove the named/taken distinction in other places.
* Multivalue type creation and inspection (#2459)Thomas Lively2019-11-221-5/+5
| | | | | | | | | | | | | 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.
* Reflect instruction renaming in code (#2128)Heejin Ahn2019-05-211-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | - 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-13/+28
| | | 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.
* Apply format changes from #2048 (#2059)Alon Zakai2019-04-261-60/+78
| | | 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
* No exit runtime pass (#1816)Alon Zakai2018-12-131-1/+1
| | | When emscripten knows that the runtime will not be exited, it can tell codegen to not emit atexit() calls (since those callbacks will never be run). This saves both code size and startup time. In asm2wasm the JSBackend does it directly. For the wasm backend, this pass does the same on the output wasm.
* Merge-Blocks improvements (#1760)Alon Zakai2018-11-261-18/+57
| | | | | | | | | | | | | | | | | | | | | | Previously we didn't try to merge a block into the parent if the block had a name. This lets us merge part of it, that is: (block (..a..) (block $child (..b..) (.. some br to $child ..) (..c..) ) ) => (block (..a..) (..b..) ;; moved out (block $child (.. some br to $child ..) (..c..) ) ) This is beneficial for 2 reasons: the child may now be a singleton, so we can remove the block; or, now that we canonicalized the br-containing code to the head of the child, we may be able to turn it into an if.
* Fix a merge-blocks fuzz bug (#1755)Alon Zakai2018-11-191-56/+0
| | | | | | * Moving blocks into if arms may change the block type, and the code we had was written under the assumption that was not true. * Move block sinking merge-blocks => remove-unused-brs, as it's more natural there. that pass refinalizes everything anyhow
* Optimize an if exit block into an if arm (#1749)Alon Zakai2018-11-151-1/+40
| | | If an if is enclosed in a block which is only used to exit one arm, move it into that arm, so it can be better optimized. Similar to what we did for loops in #1736.
* MergeBlocks: canonicalize loop exit block position on the inside (#1736)Alon Zakai2018-11-141-1/+19
| | | | * 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
* Fix a merge-blocks fuzz bug (#1730)Alon Zakai2018-11-081-1/+18
| | | | | | | | | | | | | | | 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.
* Unify imported and non-imported things (#1678)Alon Zakai2018-09-191-4/+0
| | | | | | | | | | | | | | 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.
* Merge loop tails up (#1543)Alon Zakai2018-05-101-29/+93
| | | | | | | | | | | | | | | E.g. ``` (block .. (loop $l .. (br_if $l (..)) .. code that does not branch to the loop top ) .. that code could be moved here .. ) ``` Moving the code out of the loop may help the loop body become a singleton expression, and is more readable anyhow.
* Rename WasmType => Type (#1398)Alon Zakai2018-02-021-2/+2
| | | | * rename WasmType to Type. it's in the wasm:: namespace anyhow, and without Wasm- it fits in better alongside Index, Address, Expression, Module, etc.
* notation change: AST => IR (#1245)Alon Zakai2017-10-241-2/+2
| | | 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).
* properly handle merging of blocks with concrete unreachable elements in the ↵Alon Zakai2017-08-061-6/+10
| | | | middle
* handle merging blocks with items after an unreachable, that if merged would ↵Alon Zakai2017-08-061-9/+6
| | | | be invalid. stop on the unreachable, it is easier and better
* fix merge-blocks bug with replacing an unreachable block with a concrete ↵Alon Zakai2017-08-051-4/+5
| | | | final element (which is never reached)
* fix merge-blocks logic: ensure that optimize() does not change the outside typeAlon Zakai (kripken)2017-08-051-36/+67
|
* don't move code around a drop-block when the block contains unreachables, ↵Alon Zakai2017-08-051-22/+32
| | | | which can cause type changes in the outside. dce should be run on that anyhow
* review commentsAlon Zakai (kripken)2017-07-311-5/+5
|
* don't remove values from breaks if the values have side effectsAlon Zakai (kripken)2017-07-301-11/+23
|
* when finalizing a block in MergeBlocks, use its type, so that we don't need ↵Alon Zakai2017-07-241-1/+1
| | | | to consider type changes for its parent (changing it from a forced i32 to an unreachable might mean the parent needs to become unreachable too)
* Optimizer support for atomic instructions (#1094)Derek Schuff2017-07-211-9/+18
| | | | | | * Teach EffectAnalyzer not to reorder atomics wrt other memory operations. * Teach EffectAnalyzer not to reorder host operations with memory operations * Teach various passes about the operands of AtomicRMW and AtomicCmpxchg * Factor out some functions in DeadCodeElimination and MergeBlocks
* fix merge-blocks logic in call, call_indirect, select, we need to avoid any ↵Alon Zakai (kripken)2017-07-141-6/+15
| | | | danger of moving something past a side effect ; also fix an asm2wasm bug with call_indirect fixups; the call target may be a block, which we need to look through
* handle an unreachable block with a reachable final element in merge-blocksAlon Zakai (kripken)2017-07-141-0/+9
|
* fix handling of unreachable br values in merge-blocksAlon Zakai (kripken)2017-07-111-1/+7
|
* add the option to seek named breaks, not just taken breaks; refactor headers ↵Alon Zakai (kripken)2017-07-111-1/+2
| | | | to make this practical
* Support new result syntax for if/loop/block (#1047)Sam Clegg2017-06-121-1/+1
| | | | | | Support both syntax formats in input since the old spec tests still need to be parsable.