summaryrefslogtreecommitdiff
path: root/src/passes/SimplifyGlobals.cpp
Commit message (Collapse)AuthorAgeFilesLines
* [NFC] Standardize Super:: over super:: (#6920)Alon Zakai2024-09-101-2/+2
| | | | As the name of a class, uppercase seems better here.
* SimplifyGlobals: Do not switch a get to use a global of another type (#6605)Alon Zakai2024-05-201-1/+8
| | | | If we wanted to switch types in such cases we'd need to refinalize (which is likely worth doing, though other passes should refine globals anyhow).
* Add a pass to propagate global constants to other globals (#6287)Alon Zakai2024-02-081-2/+17
| | | | | | | | | | | | | | | | | SimplifyGlobals already does this, so this is a subset of that pass, and does not add anything new. It is useful for testing, however. In particular it allows testing that we propagate subsequent globals in a single pass, that is if one global reads from another and becomes constant, then it can be propagated as well. SimplifyGlobals runs multiple passes so this always worked, but with this pass we can test that we do it efficiently in one pass. This will also be useful for comparing stringref to imported strings, as it allows gathered strings to be propagated to other globals (possible with stringref, but not imported strings) but not anywhere else (which might have downsides as it could lead to more allocations). Also add an additional test for simplify-globals that we do not get confused by an unoptimizable global.get in the middle (see last part).
* SimplifyGlobals: Propagate constant globals into nested gets in other ↵Alon Zakai2024-02-071-2/+4
| | | | | globals (#6285) Before we propagated to the top level, but not to anything interior.
* Revert "Stop propagating/inlining string constants (#6234)" (#6258)Alon Zakai2024-01-311-18/+4
| | | | | | | | | | This reverts commit 9090ce56fcc67e15005aeedc59c6bc6773220f11. This has the effect of once more propagating string constants from globals to other places (and from non-globals too), which is useful for various optimizations even if it isn't useful in the final output. To fix the final output problem, #6257 added a pass that is run at the end to collect string.const to globals, which allows us to once more propagate strings in the optimizer, now without a downside.
* Stop propagating/inlining string constants (#6234)Alon Zakai2024-01-231-4/+18
| | | | | This causes overhead atm since in VMs executing a string.const will actually allocate a string, and more copies means more allocations. For now, just do not add more. This required changes to two passes: SimplifyGlobals and Precompute.
* SimplifyGlobals: Apply constant globals to segment offsets (#6226)Alon Zakai2024-01-181-8/+32
| | | | | | | We already applied such globals to other globals, but can do the same to offsets of data and element segments. Suggested in #6220
* SimplifyGlobals: Fold single-use globals to their use (#6023)Alon Zakai2023-10-181-0/+61
| | | | | | | | | | | | | | | | For example, (global $a (struct.new $A)) (global $b (struct.new $B (global.get $A))) => (global $b (struct.new $B (struct.new $A))) and the global $a is now unused. This is valid if $a has no other uses. This saves a little in code size, but should not really help otherwise, as we already look through immutable global.get operations in important optimizations. But the code size may matter if there are many such single- use globals.
* SimplifyGlobals: Run on function code in missing places (#6020)Alon Zakai2023-10-181-4/+10
| | | | | | | | | | | | | | The pass was written before we had relevant code in module locations, but now with GC we can have global.gets of more things. The scanner did not run on global code in a way that is not a problem yet, but will be for a later PR I'll open. It will be tested there. That is, right now there is no optimization that is confused by the fact that we did not scan code at the module level, but the next PR will do that. The use modifier did not run on global code either, which was an actual missed optimization opportunity: There are cases where we want to modify a global.get to point to another one, and such a get might be in global code, not just in a function. A test is added for that.
* Asyncify: Improve comments (#5987)Heejin Ahn2023-10-031-1/+1
| | | | | | | | This fixes some outdated comments and typos in Asyncify and improves some other comments. This tries to make code comments more readable by making them more accurate and also by using the three state (normal, unwinding, and rewinding) consistently. Drive-by fix: Typo fixes in SimplifyGlobals and wasm-reduce option.
* SimplifyGlobals: Connect adjacent blocks in LinearExecutionWalker (#5865)Alon Zakai2023-08-081-0/+5
| | | | | | | Followup to #5860, this does the same for SimplifyGlobals as for SimplifyLocals. As there, this is valid because it's ok if we branch away. This part of the pass applies a global value to a global.get based on a dominating global.set, so any dominance is good enough for us.
* [Wasm GC] ReFinalize when needed in SimplifyGlobals (#5682)Alon Zakai2023-04-201-4/+23
|
* Properly use pass options in nested pass runners (up to -O1) (#5351)Alon Zakai2022-12-151-4/+12
| | | | | | | | | | | | | | | | | | This fixes a TODO. There is a runtime cost to this in higher opt levels, as passing through -O3 makes nested optimization work take longer. But it can lead to better results. For now, this PR moves us from 0 before to a maximum of 1, as a compromise. 1 does not regress compile times, but there may be further benefits to allowing 2 and 3 in the future. Also fix a fuzzer bug that becomes uncovered by tihs PR: Now that we actually optimize in simplify-globals, we need to handle the case of the optimizer there seeing a call with the effects of writing to a global (we had an assert on that never happening, but with function effects that can happen, and so a GlobalSet is not the only thing that can set a global). Aside from the opt and shrink levels this passes through all other options, like trapsNeverHappen.
* Refactor interaction between Pass and PassRunner (#5093)Thomas Lively2022-09-301-18/+18
| | | | | | | | | | | | | | 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.
* SimplifyGlobals: Handle nested read-only-to-write patterns (#4365)Alon Zakai2021-12-081-5/+21
| | | | | | | | | | | | | | | | | | | The general pattern is if (!global) { global = 1 } This PR generalizes that to handle nested appearances, if ({ if (!global) { global = 1 } !global }) { global = 1 } With this I can finally see no more "once" global operations on the hottest function in the currently slowest j2wasm benchmark ("filter"). Also added a failing testcase for something we do not handle yet.
* SimplifyGlobals: Ignore irrelevant effects in read-only-to-write (#4363)Alon Zakai2021-12-021-41/+105
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously this pass would see something like this and fail: if (foo() + global) { global = 1; } The call to foo() has side effects, so we did not optimize. However, in such a case the side effects are safe: they happen anyhow, regardless of the global that we are optimizing. That is, "global" is read only to be written, even though other things also influence the decision to write it. But "global" is not used in a way that is observable: we can remove it, and nothing will notice (except for things getting smaller/faster). In other words, this PR will let us optimize the above example, while it also needs to avoid optimizing the dangerous cases, like this: if (foo(global)) { global = 1; } Here "global" flows into a place that notices its value and may use it aside from deciding to write that global. A common case where we want to optimize is combined ifs, if (foo()) { if (global) { global = 1; } } which the optimizer turns into if (foo() & global) { global = 1; } With this PR we can handle those things too. This lets us optimize out some important globals in j2wasm like the initializer boolean for the Math object, reducing some total 0.5% of code size.
* SimplifyGlobals: If all writes write the initial value, they are unneeded ↵Alon Zakai2021-11-231-10/+32
| | | | (#4356)
* Effects: Differentiate mutable from immutable globals (#4286)Alon Zakai2021-10-291-3/+11
| | | | | | | | | | | | | Similar to what we do with structs, if a global is immutable then we know it cannot interact with calls. This changes the JS API for getSideEffects(). That was actually broken, as passing in the optional module param would just pass it along to the compiled C code, so it was coerced to 0 or 1, and not a pointer to a module. To fix that, this now does module.ptr to actually get the pointer, and this is now actually tested as without a module we cannot compute the effects of a global. This PR also makes the module param mandatory in the JS API, as again, without a module we can't compute global effects. (The module param has already been mandatory in the C++ API for some time.)
* SimplifyGlobals: Detect trivial read-only-to-write functions (#4257)Alon Zakai2021-10-191-18/+68
| | | | | | | | | | | | | | | | | | | | | We already detected code that looks like if (foo == 0) { foo = 1; } That "read only to write" pattern occurs also in functions, like this: function bar() { if (foo == 0) return; foo = 1; } This PR detects that pattern. It moves code around to share almost all the logic with the previous pattern (the git diff is not that useful there, sadly, but looking at them side by side that should be obvious). This helps in j2cl on some common clinits, where the clinit function ends up empty, which is exactly this pattern.
* Add a Module parameter to EffectAnalyzer. NFC (#4115)Alon Zakai2021-08-311-5/+3
| | | | | | | | | | | | | 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.
* SimplifyGlobals: Optimize away globals that are only read in order to write ↵Alon Zakai2021-08-101-14/+158
| | | | | | | | | | | | | | | | | | themselves (#4070) If the only uses of a global are if (global == 0) { global = 1; } Then we do not need that global: while it has both reads and writes, the value in the global does not cause anything observable. It is read, but only to write to itself, and nothing else. This happens in real-world code from j2cl quite a lot, as they have an initialization pattern with globals, and in some cases we can optimize away the work done in the initialization, leaving only the globals in this pattern.
* Add a comment in SimplifyGlobals to document existing work (#4041)Alon Zakai2021-07-301-0/+1
|
* Refactor LinearExecutionWalker to a separate file. NFC (#3956)Alon Zakai2021-06-281-0/+1
|
* Fuzz fix for SimplifyGlobals nopping (#2750)Alon Zakai2020-04-121-4/+4
| | | | We shouldn't actually nop, we forgot that the value may have side effects, so just drop it (opts will remove it later, if possible).
* Remove redundant vacume pass. Followup on #2741 (#2747)Sam Clegg2020-04-101-4/+19
| | | | Based on freedback in #2741 it looks like we can use the existing `simplify-globals-optimizing` pass to trigger this cleanups we need.
* Remove writes to globals that are never written to (#2741)Sam Clegg2020-04-091-0/+39
| | | | | Since the global is never read, we know that any write operation will be unobservable.
* Tuple globals (#2718)Thomas Lively2020-04-021-4/+4
| | | | | | | Since it wasn't easy to support tuples in Asyncify's call support using temporary functions, we decided to allow tuple-typed globals after all. This PR adds support for parsing, printing, lowering, and interpreting tuple globals and also adds validation ensuring that imported and exported globals do not have tuple types.
* makeConstExpression => makeConstantExpression (#2698)Alon Zakai2020-03-171-2/+2
| | | | | | The meaning we intend is "constant", and not the "Const" node (which contains a number). So I think the full name is less confusing.
* Handle multivalue returns in the interpreter (#2684)Thomas Lively2020-03-101-2/+2
| | | | Updates the interpreter to properly flow vectors of values, including at function boundaries. Adds a small spec test for multivalue return.
* Add EH support for EffectAnalyzer (#2631)Heejin Ahn2020-02-031-1/+1
| | | | | | | | | | | | | | | | | | | | 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`.
* Add support for reference types proposal (#2451)Heejin Ahn2019-12-301-8/+11
| | | | | | | | | | | | 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.
* SimplifyGlobals: Apply known constant values in linear traces (#2340)Alon Zakai2019-09-131-13/+73
| | | | | | | | | | | | | 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.
* SimplifyGlobals: Propagate constants in global initializers (#2238)Alon Zakai2019-07-201-7/+54
| | | | | | | | | | | (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.
* Simpify PassRunner.add() and automatically parallelize parallel functions ↵Alon Zakai2019-07-191-11/+3
| | | | | | | | | (#2242) Main change here is in pass.h, everything else is changes to work with the new API. The add("name") remains as before, while the weird variadic add(..) which constructed the pass now just gets a std::unique_ptr of a pass. This also makes the memory management internally fully automatic. And it makes it trivial to parallelize WalkerPass::run on parallel passes. As a benefit, this allows removing a lot of code since in many cases there is no need to create a new pass runner, and running a pass can be just a single line.
* SimplifyGlobals: Constant-propagate constant values of immutable globals (#2234)Alon Zakai2019-07-181-0/+43
|
* Reflect instruction renaming in code (#2128)Heejin Ahn2019-05-211-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | - 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.
* Optimize mutable globals (#2066)Alon Zakai2019-05-021-0/+143
If a global is marked mutable but not assigned to, make it immutable. If an immutable global is a copy of another, use the original, so we can remove the duplicates. Fixes #2011