summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
Commit message (Collapse)AuthorAgeFilesLines
* OptimizeAddedConstants: Handle a final added constant properly (#6115)Alon Zakai2023-11-131-9/+11
| | | | | | | | We had an assert there that was wrong. In fact the assert is just in one of two code paths, and an optional one: the end situation is we have an expression and a constant to add to it, and the assert was in the case that the expression is a Const so we can do the add at compile time (the other code path does the add at runtime). This code path is optional as Precompute would do such compile-time addition anyhow, but it is nice to fix and leave that path so that this pass emits fully optimal code.
* OptimizeInstructions: Simplify tuple.extract of tuple.make (#5938)Alon Zakai2023-09-141-0/+19
| | | | | | | | | | | | | | E.g. (tuple.extract 1 (tuple.make (A) (B) (C)) => (B) Modify some existing tests to not be in this trivial form, so that they do not stop testing what they should.
* Remove the GCNNLocals feature (#5080)Thomas Lively2023-08-311-10/+2
| | | | | Now that the WasmGC spec has settled on a way of validating non-nullable locals, we no longer need this experimental feature that allowed nonstandard uses of non-nullable locals.
* Improve cast optimizations (#5876)Thomas Lively2023-08-171-158/+148
| | | | | | | | | | | | Simplify the optimization of ref.cast and ref.test in OptimizeInstructions by moving the loop that examines fallthrough values one at a time out to a shared function in properties.h. Also simplify ref.cast optimization by analyzing the cast result in just one place. In addition to simplifying the code, also make the cast optimizations more powerful by analyzing the nullability and heap type of the cast value independently, resulting in a potentially more precise analysis of the cast behavior. Also improve optimization power by considering fallthrough values when optimizing the SuccessOnlyIfNonNull case.
* Remove legacy WasmGC instructions (#5861)Thomas Lively2023-08-091-7/+7
| | | | | Remove old, experimental instructions and type encodings that will not be shipped as part of WasmGC. Updating the encodings and text format to match the final spec is left as future work.
* OptimizeInstructions: Loop on fallthrough values in RefTest (#5797)Alon Zakai2023-07-051-31/+43
| | | | | This parallels the code in RefCast. Previously we only looked at the type reaching us, but intermediate fallthrough values can let us optimize too. In particular, we were not optimizing (ref.test (local.tee ..)) if the tee was to a less-refined type.
* Fix optimizeAddedConstants on GC-introduced unreachability (#5706)Alon Zakai2023-05-091-3/+8
|
* [Wasm GC] Fix a trapsNeverHappen corner case with if/select of a trapping ↵Alon Zakai2023-04-201-4/+22
| | | | | | | | | | | | | | | arm (#5681) The logic says that if an if/select has an arm that returns a null type, and the if/select goes into a cast, then we can ignore that arm in tnh mode (as it would trap, and we are ignoring the possibility of a trap). But it is not enough to return a null type - the null must actually flow out, rather than say a return be executed before. One existing test needed adjustment, as it used calls for "thing with effects". But a call can transfer control flow when EH is enabled, and this pass has -all. Rather than mess with the features, I switched the effects to be locals.
* [Wasm GC] OptimizeInstructions: Don't turn ref.test into unreachable ↵Alon Zakai2023-04-171-2/+6
| | | | | | | | | | | | immediately (#5673) Emit an unreachable, but guarded by a block as we do in other cases in this pass, to avoid having unreachable code that is not fully propagated during the pass (as we only do a full refinalize at the end). See existing comments starting with "Make sure to emit a block with the same type as us" in the pass. This is mostly not a problem with other casts, but ref.test returns an i32 which we have lots of code that tries to optimize.
* [Wasm GC] Casts of a non-nullable bottom type to non-null fail (#5645)Alon Zakai2023-04-121-10/+24
| | | | | | | | | | | Casting (ref nofunc) to (ref func) seems like it can succeed based on the rule of "if it's a subtype, it can cast ok." But the fuzzer found a corner case where that leads to a validation error (see testcase). Refactor the cast evaluation logic to handle uninhabitable refs directly, and return Unreachable for them (since the cast cannot even be reached). Also reorder the rule checks there to always check for a non-nullable cast of a bottom type (which always fails).
* Fix and simplify refinalization in OptimizeInstructions (#5642)Alon Zakai2023-04-071-23/+7
| | | | | The fuzzer found another case we were missing. I realized that we can just check for this in replaceCurrent, at least for places that call that method, which is the common case. So this simplifies the code while fixing a bug.
* [Wasm GC] Fix an assertion in array.set processing in OptimizeInstructions ↵Alon Zakai2023-04-071-3/+4
| | | | (#5641)
* [Wasm GC] OptimizeInstructions: ref.as_non_null of null will trap (#5635)Alon Zakai2023-04-061-0/+3
| | | | | | | Trivial peephole optimization. Some work was needed in the tests as some of them relied on that pattern for convenience, so I modified them to try to keep them testing the same thing as much as possible (for one, struct.set.null.fallthrough, I don't think we can actually keep testing the same, as the situation should not be possible any more).
* [Wasm GC] Handle another unreachability case in trapOnNull() (#5634)Alon Zakai2023-04-051-1/+2
| | | This is the flip case of #5630
* Wasm GC] Handle unreachability in a select child in trapOnNull() (#5630)Alon Zakai2023-04-051-1/+6
|
* [Wasm GC] Optimize casts to bottom types (#5484)Alon Zakai2023-02-081-8/+27
| | | | | | | | | A cast to a non-nullable null (an impossible type) must trap. In traps-never-happen mode, a cast that either returns a null or traps will definitely return a null. Followup to #5461 which emits casts to bottom types.
* Optimize ref.as_non_null removal effect computation (#5479)Alon Zakai2023-02-031-8/+14
| | | Followup to #5474
* [Wasm GC] Fix struct.set / ref.as_non_null ordering issue (#5474)Alon Zakai2023-02-021-10/+51
| | | | | | | | | | | If traps can happen, then we can't always remove a trap on null on the ref input to struct.set, since it has two children, (struct.set (ref.as_non_null X) (call $foo)) Removing the ref.as would not prevent a trap, as the struct.set will trap, but it does move the trap to after the call which is bad.
* OptimizeInstructions: Handle signed overflow properly in canOverflow() (#5467)Alon Zakai2023-01-311-13/+23
| | | | | We only checked for an unsigned overflow, which was wrong. Fixes #5464
* [Wasm GC] Refinalize fuzz fix in OptimizeInstructions cast optimizations (#5460)Alon Zakai2023-01-261-0/+6
|
* [Wasm GC] Optimize successful casts better (#5426)Thomas Lively2023-01-131-12/+33
| | | | | | Optimize ref.cast instructions that must succeed by simply replacing them with their child in the case where the child has a more refined type or by propagating a further removed fallthrough value with a more refined type using a tee.
* [Wasm GC] Optimize casts of null values better (#5423)Thomas Lively2023-01-121-30/+21
| | | | | | | | | Instead of only looking at the final fallthrough value and seeing whether it is a `RefNull` expression to determine if we are casting a null value, check the type of each intermediate fallthrough value to see if it is a null reference. Also improve `evaluateCastCheck` to return `Failure` instead of `SuccessOnlyIfNonNull` if the cast value is a reference to bottom type, since those can never be non-null.
* [Wasm GC] Generalize `skipCast` to work with all type hierarchies (#5422)Thomas Lively2023-01-121-4/+5
| | | | | | | | `skipCast` takes an optional parameter that bounds how general the resulting type is allowed to be. That parameter previously had a default value of `anyref` with the intention of allowing all casts to be skipped, but that default inadvertently prevented any casts in the `func` or `extern` type hierarchies from being skipped. Update `skipCast` so that the default parameter allows all casts to be skipped in all hierarchies.
* [Wasm GC] Add missing RefTest optimizations to parallel RefCast (#5417)Alon Zakai2023-01-101-10/+23
| | | | We already handled Success and Failure. Also handle SuccessOnlyIfNull and SuccessOnlyIfNonNull.
* Represent ref.as_{func,data,i31} with RefCast (#5413)Thomas Lively2023-01-101-25/+3
| | | | | | | | | | | | | These operations are deprecated and directly representable as casts, so remove their opcodes in the internal IR and parse them as casts instead. For now, add logic to the printing and binary writing of RefCast to continue emitting the legacy instructions to minimize test changes. The few test changes necessary are because it is no longer valid to perform a ref.as_func on values outside the func type hierarchy now that ref.as_func is subject to the ref.cast validation rules. RefAsExternInternalize, RefAsExternExternalize, and RefAsNonNull are left unmodified. A future PR may remove RefAsNonNull as well, since it is also expressible with casts.
* [NFC] Refactor cast check logic (#5404)Alon Zakai2023-01-101-96/+25
| | | Add a new evaluateCastCheck() utility and use that in relevant places.
* [Wasm GC] Optimize ref.as_non_null of a nullable cast (#5415)Alon Zakai2023-01-101-0/+16
|
* [Wasm GC] More minor cast optimizations (#5402)Alon Zakai2023-01-091-84/+89
| | | | | | | | Look for definitely-failing casts along all the fallthrough values. Specifically, if any cast in the middle proves the final cast will fail, then we know we will trap. Fully optimize redundant casts, considering both the type and the heap type. Combine a cast with a ref.as_non_null.
* Replace `RefIs` with `RefIsNull` (#5401)Thomas Lively2023-01-091-66/+15
| | | | | | | | | | | | | | | * Replace `RefIs` with `RefIsNull` The other `ref.is*` instructions are deprecated and expressible in terms of `ref.test`. Update binary and text parsing to parse those instructions as `RefTest` expressions. Also update the printing and emitting of `RefTest` expressions to emit the legacy instructions for now to minimize test changes and make this a mostly non-functional change. Since `ref.is_null` is the only `RefIs` instruction left, remove the `RefIsOp` field and rename the expression class to `RefIsNull`. The few test changes are due to the fact that `ref.is*` instructions are now subject to `ref.test` validation, and in particular it is no longer valid to perform a `ref.is_func` on a value outside of the `func` type hierarchy.
* [Wasm GC] Optimize impossible ref.casts better (#5400)Alon Zakai2023-01-061-19/+42
| | | | | | Also add some comments on related optimization opportunities. Also delete a test of a combination of types between hierarchies, which will soon not be expressible at all in the IR.
* [Wasm GC] Fix optimizations on ref.cast of null, and optimize to ↵Alon Zakai2023-01-061-1/+19
| | | | | | | | | | ref.as_non_null (#5398) We were checking the heap type, but now casts care about the nullability as well. If the nullability is the only problem, that is, the heap type will be fine but we might have a null, we can at least switch a ref.cast (non-null) to a ref.as_non_null.
* [Wasm GC] Fix non-nullable cast optimizations with multiple children (#5396)Alon Zakai2023-01-051-1/+32
| | | This fixes an oversight in #5395
* [Wasm GC] Turn casts non-nullable when they lead to a trap on null anyhow ↵Alon Zakai2023-01-051-0/+15
| | | | (#5395)
* [Wasm GC] Clean up and improve null trap and cast optimizations (#5394)Alon Zakai2023-01-051-20/+21
| | | | | | | | | visitRefCast can use trapOnNonNull. To make this not regress, add fallthrough analysis there as well. Minor test changes are due to trapOnNonNull using getDroppedChildren which only emits drops of necessary children. It also tells us to refinalize so it is ok for it to change the type to unreachable.
* wasm2js: Avoid emitting non-JS code during opt (#5378)Will Cohen2023-01-041-1/+4
| | | | | | | | | | | As noted in #4806, trying to optimize past level 0 can result in passes emitting non-JS code, which is then unable to be converted during final output. This commit creates a new targetJS option in PassOptions, which can be checked inside each pass where non-JS code might be emitted. This commit initially adds that logic to OptimizeInstructions, where this issue was first noticed.
* Allow non-nullable ref.cast of nullable references (#5386)Thomas Lively2023-01-041-21/+21
| | | | | | | This new cast configuration was not expressible with the legacy cast instructions. Although it is valid in Wasm, do not allow nullable casts of non-nullable references, since those would unnecessarily lose type information. Convert such casts to be non-nullable during expression finalization.
* Support `ref.test null` (#5368)Thomas Lively2022-12-211-5/+14
| | | This new variant of ref.test returns 1 if the input is null.
* OptimizeInstructions: Check for possible added-constant overflows (#5227)Alon Zakai2022-12-201-14/+99
| | | | | | | | | | | Fix a regression from #5025 : we subtract constants there, and we need to be aware that such subtraction can change a constant from signed to unsigned if the comparison is signed, as 0x80000000 - 1 = 0x7fffffff 0x8000000 is a negative number when seen as signed, but always positive after the subtraction.
* Update RefCast representation to drop extra HeapType (#5350)Thomas Lively2022-12-201-2/+7
| | | | | | | | | The latest upstream version of ref.cast is parameterized with a target reference type, not just a heap type, because the nullability of the result is parameterizable. As a first step toward implementing these new, more flexible ref.cast instructions, change the internal representation of ref.cast to use the expression type as the cast target rather than storing a separate heap type field. For now require that the encoded semantics match the previously allowed semantics, though, so that none of the optimization passes need to be updated.
* [Wasm GC] Optimize away null arms that would trap (#5358)Alon Zakai2022-12-161-5/+74
| | | | | | | | | | | | | | | | | | | | | | | | E.g. (struct.get (select (ref.null ..) (something) (condition) ) ) If traps-never-happen then this can be (drop (condition)) (struct.get (something) ) That is, we can remove the arm that is null, as it would trap but traps are assumed to not happen. Also fix a bug this uncovers on struct.set on a null type.
* Fix a fuzz bug with incremental unreachability in OptimizeInstructions (#5237)Alon Zakai2022-11-091-1/+7
| | | | | | | | | | | OptimizeInstructions in rare cases can add unreachability. We propagate it out at the end all at once. The fuzzer was smart enough to find a very special combination of code + passes that can hit an issue, see the testcase. As mentioned in the TODO, we should perhaps avoid adding unreachability in OptimizeInstructions at all. If this happens again that might be worth the effort. But also checking the type of the child as in this PR doesn't add much complexity in the code.
* [Wasm GC] Externalize/Internalize allow nulls (#5175)Alon Zakai2022-10-211-0/+6
| | | | | These are encoded as RefAs operations, and we have optimizations that assume those trap on null, but Externalize/Internalize do not. Skip them there to avoid an error on the type being incorrect later.
* Implement bottom heap types (#5115)Thomas Lively2022-10-071-3/+34
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | These types, `none`, `nofunc`, and `noextern` are uninhabited, so references to them can only possibly be null. To simplify the IR and increase type precision, introduce new invariants that all `ref.null` instructions must be typed with one of these new bottom types and that `Literals` have a bottom type iff they represent null values. These new invariants requires several additional changes. First, it is now possible that the `ref` or `target` child of a `StructGet`, `StructSet`, `ArrayGet`, `ArraySet`, or `CallRef` instruction has a bottom reference type, so it is not possible to determine what heap type annotation to emit in the binary or text formats. (The bottom types are not valid type annotations since they do not have indices in the type section.) To fix that problem, update the printer and binary emitter to emit unreachables instead of the instruction with undetermined type annotation. This is a valid transformation because the only possible value that could flow into those instructions in that case is null, and all of those instructions trap on nulls. That fix uncovered a latent bug in the binary parser in which new unreachables within unreachable code were handled incorrectly. This bug was not previously found by the fuzzer because we generally stop emitting code once we encounter an instruction with type `unreachable`. Now, however, it is possible to emit an `unreachable` for instructions that do not have type `unreachable` (but are known to trap at runtime), so we will continue emitting code. See the new test/lit/parse-double-unreachable.wast for details. Update other miscellaneous code that creates `RefNull` expressions and null `Literals` to maintain the new invariants as well.
* Refactor standardizeNaN (#5064)Max Graey2022-10-041-5/+1
| | | Change `standardizeNaN` to take a `Literal` to reduce usage verbosity.
* 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.
* [OptimizeInstruction] Prevent reordering for rule in #5034 (#5066)Max Graey2022-09-211-2/+3
|
* [OptimizeInstructions] Simplify add / sub with negative on LHS or RHS for ↵Max Graey2022-09-201-0/+25
| | | | | | | | | floating points (#5034) ``` (-x) + y -> y - x x + (-y) -> x - y x - (-y) -> x + y ```
* [OptimizeInstructions] More canonizations for floating points (#5033)Max Graey2022-09-151-14/+5
| | | | | | | | x - C -> x + (-C) min(C, x) -> min(x, C) max(C, x) -> max(x, C) And remove redundant rules
* Move relational-optimizing code to optimizeRelational [NFC] (#5036)Alon Zakai2022-09-131-33/+35
| | | | | | This just moves the code from #5025 to the right function, which I did not realize existed. optimizeRelational is where we optimize binary operations that do comparisons, and it's nice to put all that code together. Avoids repeated checks of isRelational() in separate places.
* OptimizeInstructions: Use min/max bits in comparisons (#5035)Alon Zakai2022-09-131-6/+84
| | | | | | | When we see e.g. x < y and x has fewer bits set, we can infer a result. Helps #5010. As mentioned there, this is one of the top superoptimizer findings. On j2wasm it ends up removing a few hundred binary operations for example.