summaryrefslogtreecommitdiff
path: root/test
Commit message (Collapse)AuthorAgeFilesLines
* Support `ref.test null` (#5368)Thomas Lively2022-12-215-10/+476
| | | 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-0/+299
| | | | | | | | | | | 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.
* Work around bugs with open world type optimizations (#5367)Thomas Lively2022-12-2010-22/+16
| | | | | | | | | | | | | | Since #5347 public types are never updated by type optimizations, but the optimization passes have not yet been updated to take that into account, so they are all buggy under an open world assumption. In #5359 we worked around many closed world validation errors in the fuzzer by treating --closed-world like a feature flag and checking whether it was necessary for fuzzer input, but that did not prevent the type optimization passes from running under an open world, so it did not work around all the potential issues. Work around the problem more thoroughly by not running any type optimization passes in the fuzzer without --closed-world. Also add logic to those passes to error out if they are run without --closed-world and update the tests accordingly.
* Update RefCast representation to drop extra HeapType (#5350)Thomas Lively2022-12-204-10/+23
| | | | | | | | | 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] Do not cache signature types in nominal mode if they have a super ↵Alon Zakai2022-12-191-0/+41
| | | | | | | (#5364) This reduces the amount of public types, since if there is a super then using the type in a public place would make the super also public. It is safer for closed-world mode to reuse types without supers.
* Remove unused types during type optimizations (#5361)Thomas Lively2022-12-194-1/+50
| | | | | | | | | | | | | | | | | | | | | The type rewriting utility in type-updating.cpp gathers all the used heap types, then rewrites them to newly built and possibly modified heap types. The problem is that for the isorecursive type system, the set of "used" heap types was overly broad because it also included unused heap types that are in a rec group with used types. In the context of emitting a binary, it is important to treat these types as used because failing to emit them would change the identity of the used types, but in the context of type optimizations it is ok to treat them as truly unused because we are changing type identities anyway. Update the type rewriting utility to only include truly used types in the set of output types. This causes all existing type optimizations to implicitly drop unused types, but only if they find any other optimizations to do and actually run the rewriter utitility. Their output will also still include unused types that were used before their optimizations were applied. To overcome these limitations and better match the optimizing power of nominal mode, which never includes unused types in the output, add a new type optimization pass that removes unused types and does nothing else and run it near the end of the global optimization pipeline.
* Do not optimize public types (#5347)Thomas Lively2022-12-164-48/+130
| | | | | | | | | | | | | | | | | Do not optimize or modify public heap types in any way. Public heap types include the types of imported or exported functions, tables, globals, etc. This is important to maintain the public interface of a module and ensure it can still link interact as intended with the outside world. Also add validation error if we find any nontrivial public types that are not the types of imported or exported functions. This error is meant to help the user ensure that type optimizations are not silently inhibited. In the future, we may want to add options to silence this error or downgrade it to a warning. This commit only updates the type updating machinery to avoid updating public types. It does not update any optimization passes accordingly. Since we avoid modifying public signature types already, this is not expected to break anything, but in the future once we have function subtyping or if we make the error optional, we may have to update some of our optimization passes.
* [Wasm GC] Optimize away null arms that would trap (#5358)Alon Zakai2022-12-161-3/+287
| | | | | | | | | | | | | | | | | | | | | | | | 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.
* In --debug mode, print partial wasm data that was read (#5356)Alon Zakai2022-12-153-63/+105
| | | | | | | | | | | | | | | | | | | If wasm-opt or wasm-dis are given an invalid binary, after the error message we can also print out the wasm we did manage to read. That includes global stuff like imports and also all the functions up until there. This can help debugging in some situations. Only do this when --debug is passed as it can be very verbose and in general users might not want it. This is technically easy to do, it turns out, since we already use a thrown exception on an error in parsing, and we fill up the wasm as we go, so it just contains what we've read so far, and we can just print it. Fixes #5344 Also switch an existing test's comments to ;; from # which was noticed here.
* Properly use pass options in nested pass runners (up to -O1) (#5351)Alon Zakai2022-12-151-0/+91
| | | | | | | | | | | | | | | | | | 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.
* Add memory: init, copy, fill support to Multi-Memory Lowering Pass (#5346)Ashley Nelson2022-12-151-4/+179
| | | This PR adds support for memory.init, memory.copy, and memory.fill instructions in the multi-memory lowering pass. Also includes optional bounds checks per the wasm spec guidelines.
* Replace more uses of `NAN` (#5354)Thomas Lively2022-12-151-2/+2
| | | | MSVC is making `NAN` negative, so use an explicitly constructed positive NaN instead.
* Fix opt/shrink levels when running the optimizer multiple times (#5333)Alon Zakai2022-12-141-0/+18
| | | | | | | | | | Previously -O3 -O1 would run -O1 twice since the last flag set the global opt level to 1, and then all invocations of the optimizer pipeline read that. This makes each pipeline define its own opt level. This has been a long-standing annoyance, which wasn't much noticed except that with wasm GC there is more of a need to run the optimization pipeline more than once. And sometimes it is nice to run different levels.
* [Wasm GC] Fix GlobalStructInference on unrefined globals (#5338)Alon Zakai2022-12-121-0/+93
| | | | | | | If a global's type is not fully refined, then when --gsi replaces a reference with a global.get, we end up with a type that might not be good enough. For example, if the type is any then it is not a subtype of eq and we can't do ref.eq on it, which this pass requires. We also can't just do struct.get on it if it is a too-distant parent or such.
* Add Atomics support to Multi-Memory Lowering Pass (#5339)Ashley Nelson2022-12-121-2/+185
| | | | | This PR adds support for Atomic instructions in the multi-memory lowering pass. Also includes optional bounds checks per the wasm spec guidelines, (visitAtomicRMW, visitAtomicCmpxchg, visitAtomicWait, visitAtomicNotify). Note: The latter two instructions, memory.atomic.wait and memory.atomic.notify, have browser engine implementations that predate the still-in-progress threads spec. And whether or not atomic.notify should trap for out-of-bounds addresses remains an open issue. For now, this PR is using the same semantics as v8, which is to bounds check all Atomic instructions the same way and trap for out-of-bounds.
* Add SIMD support to Multi-Memory Lowering Pass (#5336)Ashley Nelson2022-12-121-2/+170
| | | This PR adds support for SIMD instructions in the multi-memory lowering pass. Also includes optional bounds checks per the wasm spec guidelines, (SIMDLoad, SIMDLoadSplat, SIMDLoadExtend, SIMDLoadZero, SIMDLoadStoreLane load | store).
* Adds bounds checks to Load/Store in Multi-Memories Lowering Pass (#5256)Ashley Nelson2022-12-093-0/+349
| | | Per the wasm spec guidelines for Load (rule 10) & Store (rule 12), this PR adds an option for bounds checking, producing a runtime error if the instruction exceeds the bounds of the particular memory within the combined memory.
* Use non-nullable ref.cast for non-nullable input (#5335)Thomas Lively2022-12-0918-131/+130
| | | | | | | | | | | | We switched from emitting the legacy `ref.cast_static` instruction to emitting `ref.cast null` in #5331, but that wasn't quite correct. The legacy instruction had polymorphic typing so that its output type was nullable if and only if its input type was nullable. In contrast, `ref.cast null` always has a a nullable output type. Fix our output by instead emitting non-nullable `ref.cast` if the output should be non-nullable. Parse `ref.cast` in binary and text forms as well. Since the IR can only represent the legacy polymorphic semantics, disallow unsupported casts from nullable to non-nullable references or vice versa for now.
* Allow casting to basic heap types (#5332)Thomas Lively2022-12-088-106/+173
| | | | | | | The standard casting instructions now allow casting to basic heap types, not just user-defined types, but they also require that the intended type and argument type have a common supertype. Update the validator to use the standard rules, update the binary parser and printer to allow basic types, and update the tests to remove or modify newly invalid test cases.
* Add standard versions of WasmGC casts (#5331)Thomas Lively2022-12-0735-467/+582
| | | | | | | We previously supported only the non-standard cast instructions introduced when we were experimenting with nominal types. Parse the names and opcodes of their standard counterparts and switch to emitting the standard names and opcodes. Port all of the tests to use the standard instructions, but add additional tests showing that the non-standard versions are still parsed correctly.
* [Wasm GC] Add array support to TypeMerging (#5329)Alon Zakai2022-12-071-0/+41
|
* [Wasm GC] Add TypeMerging pass (#5321)Alon Zakai2022-12-074-0/+390
| | | | | | | | This finds types that can be merged into their super: types that add no fields, and are not used in casts, etc. - so we might as well use the super. This complements TypeSSA, in that it can merge back the new types that TypeSSA created, if we never found a use for them. Without this, TypeSSA can bloat binary size quite a lot (I see 10-20%).
* Update tests ahead of transition from `data` to `struct` (#5320)Thomas Lively2022-12-0731-787/+302
| | | | | | | | | | The upstream WasmGC spec has removed `data` and introduced `struct`. To make the migration easier, we have been supporting `struct` as an `alias` for `data` and `structref` as an alias for `dataref`. Update the tests to prefer the `struct` aliases over `data` for test input to make the future migration easier. Also update some tests that had stale comments about ref.null types being updated and remove some tests for instructions like br_on_data and ref.as_data that do not make sense without a `data` type.
* [Wasm GC] Add array support to TypeSSA (#5327)Alon Zakai2022-12-071-0/+230
| | | Previously it only handled structs.
* Fix Asyncify assertions after #5293 (#5328)Alon Zakai2022-12-071-7/+74
| | | | | | | | | | | Followup to #5293, this fixes a small regression there regarding assertions. We do have a need to visit non-instrumented functions if we want assertions, as we assert on some things there, namely that such functions do not change the state (if they changed it, we'd need to instrument them to handle that properly). This moves that logic into a new pass. We run that pass when assertions are enabled. Test diff basically undoes part the test diff from that earlier PR for that one file.
* Fix an Inlining bug with a name collision in a br nested in a call param (#5323)Alon Zakai2022-12-061-0/+44
|
* Optimize Asyncify to not flatten/optimize unnecessarily (#5293)Alexander Guryanov2022-12-068-215/+45
| | | | | | | | | Add a way to proxy passes and the addition of passes in pass runners. With that we can make Asyncify only modify functions it actually needs to. On a project that Asyncify only needs to modify a few functions on, this can save a huge amount of time as it avoids flattening+optimizing the majority of the module. Fixes #4822
* [Wasm GC] Add TypeSSA pass (#5299)Alon Zakai2022-12-023-0/+227
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This creates new nominal types for each (interesting) struct.new. That then allows type-based optimizations to be more precise, as those optimizations will track separate info for each struct.new, in effect. That is kind of like SSA, however, we do not handle merges. For example: x = struct.new $A (5); print(x.value); y = struct.new $A (11); print(y.value); // => // x = struct.new $A.x (5); print(x.value); y = struct.new $A.y (11); print(y.value); After the pass runs each of those struct.new creates a unique type, and type-based analysis can see that 5 or 11 are the only values written in that type (if nothing else writes there). This bloats the type section with the new subtypes, so it is best used with a pass to merge unneeded duplicate types, which a later PR will add. That later PR will exactly merge back in the types created here, which are nominally different but indistinguishable otherwise. This pass is not enabled by default. It's not clear yet where is the best place to do it, as it must be balanced by type merging, but it might be better to do multiple rounds of optimization between the two. Needs more investigation.
* Remove more uses of NAN (#5310)Thomas Lively2022-12-021-8/+10
| | | | | In favor of the more portable code snippet using `std::copysign`. Also reintroduce assertions that the NaNs have the expected signs. This continues work started in #5302.
* Support `array` and `struct` types in the type fuzzer (#5308)Thomas Lively2022-12-022-41/+47
| | | | | | | Since `data` has been removed from the upstream proposal and `struct` has been added in its place, update the type fuzzer to be structured around `struct` and `array` (which it had not previously been updated to support) rather than `data`. A follow-on PR will make the broader change of removing `data` and adding `struct`.
* Do not special case ref.null in `LUBFinder` (#5307)Thomas Lively2022-12-016-58/+101
| | | | | | | | | | | | Before we implemented bottom heap types, `ref.null` had to be annotated with specific types. The `LUBFinder` utility ignored these types so that it could find the best LUB from all considered non-null expressions, then go back and update the type annotations on the nulls to match that LUB. Now that we have bottom types, however, none of that is necessary, and in fact ignoring nulls can miss possible refinements to bottom types. Update and simplify `LUBFinder` so that it is a simple wrapper around the underlying `Type::getLeastUpperBound` utility with no additional logic. Update tests to account for the more powerful optimizations.
* [Wasm GC] Implement closed-world flag (#5303)Alon Zakai2022-11-304-23/+256
| | | | | | | | | | | | | With this change we default to an open world, that is, we do the safe thing by default: we no longer assume a closed world. Users that want a closed world must pass --closed-world. Atm we just do not run passes that assume a closed world. (We might later refine them to find which types don't escape and only optimize those.) The RemoveUnusedModuleElements is an exception in that the closed-world flag influences one part of its operation, but not the rest. Fixes #5292
* [NFC] Avoid unneeded work in GTO (#5304)Alon Zakai2022-11-305-21/+9
| | | | | As noticed in #5303, the test changes here are because we did unnecessary work which created a new rec group, which then led to a rec group being printed out.
* Fix validation and inlining bugs (#5301)Thomas Lively2022-11-291-4/+40
| | | | | | | | | | | | | | Inlining had a bug where it gave return_calls in inlined callees concrete types even when they should have remained unreachable. This bug flew under the radar because validation had a bug where it allowed expressions to have concrete types when they should have been unreachable. The fuzzer found this bug by adding another pass after inlining where the unexpected types caused an assertion failure. Fix the bugs and add a test that would have triggered the inlining bug. Unfortunately the test would have also passed before this change due to the validation bug, but it's better than nothing. Fixes #5294.
* Add a placeholder closed-world flag (#5298)Alon Zakai2022-11-292-0/+18
| | | The flag does nothing so far.
* Remove equirecursive typing (#5240)Thomas Lively2022-11-2323-333/+161
| | | | Equirecursive is no longer standards track and its implementation is extremely complex. Remove it.
* Change the default type system to isorecursive (#5239)Thomas Lively2022-11-23319-4610/+4590
| | | | | | | | | | This makes Binaryen's default type system match the WasmGC spec. Update the way type definitions without supertypes are printed to reduce the output diff for MVP tests that do not involve WasmGC. Also port some type-builder.cpp tests from test/example to test/gtest since they needed to be rewritten to work with isorecursive type anyway. A follow-on PR will remove equirecursive types completely.
* [Wasm GC] Fix CoalesceLocals on tees that receive a refined type (#5289)Alon Zakai2022-11-221-0/+51
| | | Same testcase as in #5287 but in another pass.
* [Wasm GC] Refinalize in UnneededSetRemover when necessary (#5287)Alon Zakai2022-11-221-6/+31
|
* Validate that GC is enabled for rec groups and supertypes (#5279)Thomas Lively2022-11-222-0/+30
| | | | | | | | | Update `HeapType::getFeatures` to report that GC is used for heap types that have nontrivial recursion groups or supertypes. Update validation to check the features on function heap types, not just their individual params and results. This fixes a fuzz bug in #5239 where initial contents included a rec group but the fuzzer disabled GC. Since the resulting module passed validation, the rec groups made it into the binary output, making the type section malformed.
* Code Pushing: Ignore unreachable sets (#5284)Alon Zakai2022-11-211-1/+29
| | | | | Normally we ignore them anyhow (unreachability is an effect, either a trap or a control flow switch), but in traps-never-happen mode we can ignore a trap, so we need to check this manually.
* Do not compare reference values across executions (#5276)Thomas Lively2022-11-171-0/+22
| | | | | | | Since we optimize assuming a closed world, optimizations can change the types and structure of GC data even in externally-visible ways. Because differences are expected, the fuzzer already did not compare reference-typed values from before and after optimizations when running with nominal typing. Update it to not compare these values under any type system.
* [Wasm GC] Start an OptimizeCasts pass and reuse cast values there (#5263)Alon Zakai2022-11-173-0/+402
| | | | | | | | | | | | | | | | | | | | | | | | (some.operation (ref.cast .. (local.get $ref)) (local.get $ref) ) => (some.operation (local.tee $temp (ref.cast .. (local.get $ref)) ) (local.get $temp) ) This can help cases where we cast for some reason but happen to not use the cast value in all places. This occurs in j2wasm in itable calls sometimes: The this pointer is is refined, but the itable may be done with an unrefined pointer, which is less optimizable. So far this is just inside basic blocks, but that is enough for the cast of itable calls and other common patterns I see.
* Fix isorecursive canonicalization (#5269)Thomas Lively2022-11-171-1/+1
| | | | | | | | | | | | | | Fixes a longstanding problem with isorecursive canonicalization that only showed up in MacOS and occasionally Windows builds. The problem was that `RecGroupEquator` was not quite correct in the presence of self-references in rec groups. Specifically, `RecGroupEquator` did not differentiate between instances of the same type appearing across two rec groups where the type was a self-reference in one group but not in the other. The reason this only showed up occasionally on some platforms was that this bug could only cause incorrect behavior if two groups that would incorrectly be compared as equal were hashed into the same bucket of a hash map. Apparently the hash map used on Linux never hashes the two problematic groups into the same bucket.
* Revert "Revert "Make `call_ref` type annotations mandatory (#5246)" (#5265)" ↵Thomas Lively2022-11-1617-76/+81
| | | | | (#5266) This reverts commit 570007dbecf86db5ddba8d303896d841fc2b2d27.
* Revert "Make `call_ref` type annotations mandatory (#5246)" (#5265)Thomas Lively2022-11-1617-81/+76
| | | | | This reverts commit b2054b72b7daa89b7ad161c0693befad06a20c90. It looks like the necessary V8 change has not rolled out everywhere yet.
* [Wasm GC] Fix a GUFA bug on null call_ref targets (#5262)Alon Zakai2022-11-161-2/+22
| | | | If the target is a bottom type then it is a heap type but it is not a signature type, and we should treat it as unreachable (and not crash).
* GlobalStructInference: Handle the case of just 1 value (#5259)Alon Zakai2022-11-152-6/+61
| | | | | | | | | | | | #5253 handled the case of just one possible global. It is also possible we have multiple globals but just one value. This handles that case. (It slightly overlaps with other passes, but as this pass actually identifies the creations of the objects in globals, it has a guarantee of success that the others don't, and it is very easy to just do given all the work done to handle the case of 2 values). Also fix a minor bug in #5253 - we need to trap if the old reference were null. That is, we know the reference must point to the only object ever created of that type, but that is only if it is not null; if it's null we need to trap.
* [Parser] Parse struct allocation and accessor instructions (#5255)Thomas Lively2022-11-151-1/+80
| | | | | Including support for parsing field indices. Although only numeric field indices are supported at the moment, set up the code to make it straightforward to implement type-dependent symbolic field names in the future.
* GlobalStructInference: Handle cases with just 1 global too (#5253)Alon Zakai2022-11-152-19/+171
| | | | | | | | | | | | | | | | | | | | | Expand GlobalStructInference to operate on cases with a single possible global, and not just 2 or more. Even the case of a single global is useful, it turns out, as we can alter the reference in places like this: (struct.get $type 0 (..ref..) ) No matter what ref is, if there is a single global it must refer to, we can switch to this: (struct.get $type 0 (global.get $global) ) That can unlock further opts later. Note that we can do this even if we don't know what the value actually is - we may not know what the struct.get returns, but we do know what it reads from.