summaryrefslogtreecommitdiff
path: root/src/passes
Commit message (Collapse)AuthorAgeFilesLines
...
* Ensure printed tuple.extract arity is valid (#6487)Thomas Lively2024-04-111-1/+6
| | | | | | We previously printed the size of the tuple operand as the arity, but that printed `1` when the operand is unreachable. We don't allow our text input to use `1` as the arity, so don't print it, either. Instead, print the smallest valid arity, `2`, in this case.
* Heap2Local: Fix signed struct/array reads (#6484)Alon Zakai2024-04-101-5/+10
| | | | | | In #6480 I forgot that StructGet can be signed, which means we need to emit a sign-extend. Arrays already copied the field as part of Array2Struct.
* Improve inlining of `return_call*` (#6477)Jérôme Vouillon2024-04-101-28/+60
| | | | | Use the previous implementation when no return_call is in a try block. This avoids moving code around (as a sibling of the caller body or the inlined body), so that should allow more local optimizations after inlining.
* Heap2Local: Optimize packed fields (#6480)Alon Zakai2024-04-091-12/+26
| | | | | | Previously we did not optimize a struct or an array with a packed field. As a result a single packed field in a struct prevented the entire struct from being localized, which this fixes. This is also useful for arrays as packed arrays are common (e.g. for string data).
* Heap2Local: Optimize Arrays in addition to Structs (#6478)Alon Zakai2024-04-091-21/+322
| | | | | | | | | | | | To keep things simple, this adds a Array2Struct component to the pass. When we find a non-escaping array, we run that to turn it into a struct, and then run the existing Struct2Local to convert that to locals. This avoids refactoring Struct2Local to handle both structs and arrays (with the downside of making the optimization of arrays a little less efficient, but they are rarer, I suspect - that is certainly the case in Java output I've seen). The core EscapeAnalyzer logic is generalized to handle both arrays and structs, but the changes there are thankfully quite minor.
* Asyncify: Fix nondeterminism in verbose logging (#6479)Alon Zakai2024-04-091-4/+17
| | | | #6457 added a test that exposed existing nondeterminism.
* Handle return calls in CodeFolding (#6474)Thomas Lively2024-04-081-1/+21
| | | | Treat them the same as returns and test that they can be folded out of try-catch blocks because they do not have throws effects.
* Handle return calls correctlyThomas Lively2024-04-081-58/+152
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a combined commit covering multiple PRs fixing the handling of return calls in different areas. The PRs are all landed as a single commit to ensure internal consistency and avoid problems with bisection. Original PR descriptions follow: * Fix inlining of `return_call*` (#6448) Previously we transformed return calls in inlined function bodies into normal calls followed by branches out to the caller code. Similarly, when inlining a `return_call` callsite, we simply added a `return` after the body inlined at the callsite. These transformations would have been correct if the semantics of return calls were to call and then return, but they are not correct for the actual semantics of returning and then calling. The previous implementation is observably incorrect for return calls inside try blocks, where the previous implementation would run the inlined body within the try block, but the proper semantics would be to run the inlined body outside the try block. Fix the problem by transforming inlined return calls to branches followed by calls rather than as calls followed by branches. For the case of inlined return call callsites, insert branches out of the original body of the caller and inline the body of the callee as a sibling of the original caller body. For the other case of return calls appearing in inlined bodies, translate the return calls to branches out to calls inserted as siblings of the original inlined body. In both cases, it would have been convenient to use multivalue block return to send call parameters along the branches to the calls, but unfortunately in our IR that would have required tuple-typed scratch locals to unpack the tuple of operands at the call sites. It is simpler to just use locals to propagate the operands in the first place. * Fix interpretation of `return_call*` (#6451) We previously interpreted return calls as calls followed by returns, but that is not correct both because it grows the size of the execution stack and because it runs the called functions in the wrong context, which can be observable in the case of exception handling. Update the interpreter to handle return calls correctly by adding a new `RETURN_CALL_FLOW` that behaves like a return, but carries the arguments and reference to the return-callee rather than normal return values. `callFunctionInternal` is updated to intercept this flow and call return-called functions in a loop until a function returns with some other kind of flow. Pull in the upstream spec tests return_call.wast, return_call_indirect.wast, and return_call_ref.wast with light editing so that we parse and validate them successfully. * Handle return calls in wasm-ctor-eval (#6464) When an evaluated export ends in a return call, continue evaluating the return-called function. This requires propagating the parameters, handling the case that the return-called function might be an import, and fixing up local indices in case the final function has different parameters than the original function. * Update effects.h to handle return calls correctly (#6470) As far as their surrounding code is concerned return calls are no different from normal returns. It's only from a caller's perspective that a function containing a return call also has the effects of the return-callee. To model this more precisely in EffectAnalyzer, stash the throw effect of return-callees on the side and only merge it in at the end when analyzing the effects of a full function body.
* Asyncify-verbose: Show all reasons why a function is instrumented (#6457)Dannii Willis2024-04-082-8/+8
| | | | Helps emscripten-core/emscripten#17380 by logging all the reasons why we instrument a function, and not just the first as we did before.
* [NFC] Refactor Heap2Local logic (#6473)Alon Zakai2024-04-061-352/+389
| | | | | | Separate out an EscapeAnalyzer class that does the escape analysis, and a Struct2Local one that does the optimization. Also make a few things const here to be safer.
* Add an Asyncify option to propagate the addList (#5935)かめのこにょこにょこ2024-04-011-12/+42
| | | | | The new asyncify flag --pass-arg=asyncify-propagate-addlist changes the behavior of --pass-arg=asyncify-addlist : with it, callers of functions in the asyncify-addlist will be also instrumented.
* [Strings] Lower string.concat in StringLowering (#6453)Thomas Lively2024-03-291-0/+9
|
* Remove "minimal" JS import/export legalization (#6428)Sam Clegg2024-03-223-42/+6
| | | | | | | | | | | | This change removes the "minimal" mode from `LegalizeJSInterface` which was added in #1883. The idea behind this change was to avoid legalizing most function except those we know that JS will be calling. The idea was that for dynamic linking we always want the non-legalized version to be shared between wasm module. These days we solve this problem in a different way with the `legalize-js-interface-export-originals` which exports the original functions alongside the legalized ones. Emscripten then always prefers the `$orig` functions when doing dynamic linking.
* [Strings] Represent string values as WTF-16 internally (#6418)Thomas Lively2024-03-222-2/+14
| | | | | | | | | | | | | | | | WTF-16, i.e. arbitrary sequences of 16-bit values, is the encoding of Java and JavaScript strings, and using the same encoding makes the interpretation of string operations trivial, even when accounting for non-ascii characters. Specifically, use little-endian WTF-16. Re-encode string constants from WTF-8 to WTF-16 in the parsers, then back to WTF-8 in the writers. Update the constructor for string `Literal`s to interpret the string as WTF-16 and store a sequence of WTF-16 code units, i.e. 16-bit integers. Update `Builder::makeConstantExpression` accordingly to convert from the new `Literal` string representation back to a WTF-16 string. Update the interpreter to remove the logic for detecting non-ascii characters and bailing out. The naive implementations of all the string operations are correct now that our string encoding matches the JS string encoding.
* Precompute: Mark StringEncode as non-removable, just like ArrayCopy (#6423)Alon Zakai2024-03-221-1/+8
| | | | | | | | | | | | | | The only StringEncode we support is the one that writes into an array, so it has the same effects as ArrayCopy. Precompute needs to be made aware of such side effects in a manual manner (as we already do for ArrayCopy etc.): it simply tries to execute code in the interpreter, and if it succeeds it replaces; it does not check for side effects (checking for side effects would prevent optimizing cases where the side effects do not happen, as we check them statically, e.g. dividing by a non-zero constant does not trap but a division would be seen as having a potential trap effect). I verified no other string operation is hit by this: all the others emit or operate on immutable strings; it is just StringEncode that is basically an Array operation that appears in the Strings proposal.)
* CodeFolding: Fix up old EH when we fold away an If (#6420)Alon Zakai2024-03-221-0/+12
| | | | | | | | | | | | | | | | | | | | | The pass does (among other things) this: (if condition X X ) => (block (drop condition ) X ;; deduplicated ) After that the condition is now nested in a block, so we may need EH fixups if it contains a pop.
* Revert "Strings: Disable precomputing for now (#6412)" (#6413)Alon Zakai2024-03-201-30/+0
| | | | | | | | This reverts commit 70ac213fce134840609190a5d3a18118a089ba8a. Reverts #6412 On second thought we found a way to make fixing this less urgent, and the code size downsides of this are worrying, so let's revert it.
* Strings: Disable precomputing for now (#6412)Alon Zakai2024-03-201-0/+30
| | | | Our UTF implementation is still not fully stable it seems as we have reports of issues. Disable it for now.
* Typed continuations: suspend instructions (#6393)Frank Emrich2024-03-192-0/+6
| | | | | | | | | | | | | | | | | | | | | This PR is part of a series that adds basic support for the [typed continuations/wasmfx proposal](https://github.com/wasmfx/specfx). This particular PR adds support for the `suspend` instruction for suspending with a given tag, documented [here](https://github.com/wasmfx/specfx/blob/main/proposals/continuations/Overview.md#instructions). These instructions are of the form `(suspend $tag)`. Assuming that `$tag` is defined with _n_ `param` types `t_1` to `t_n`, the instruction consumes _n_ arguments of types `t_1` to `t_n`. Its result type is the same as the `result` type of the tag. Thus, the folded textual representation looks like `(suspend $tag arg1 ... argn)`. Support for the instruction is implemented in both the old and the new wat parser. Note that this PR does not implement validation of the new instruction. This PR also fixes finalization of `cont.new`, `cont.bind` and `resume` nodes in those cases where any of their children are unreachable.
* DeadArgumentElimination/SignaturePruning: Prune params even if called with ↵Alon Zakai2024-03-184-62/+277
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | effects (#6395) Before this PR, when we saw a param was unused we sometimes could not remove it. For example, if there was one call like this: (call $target (call $other) ) That nested call has effects, so we can't just remove it from the outer call - we'd need to move it first. That motion was hard to integrate which was why it was left out, but it turns out that is sometimes very important. E.g. in Java it is common to have such calls that send the this parameter as the result of another call; not being able to remove such params meant we kept those nested calls alive, creating empty structs just to have something to send there. To fix this, this builds on top of #6394 which makes it easier to move all children out of a parent, leaving only nested things that can be easily moved around and removed. In more detail, DeadArgumentElimination/SignaturePruning track whether we run into effects that prevent removing a field. If we do, then we queue an operation to move the children out, which we do using a new utility ParamUtils::localizeCallsTo. The pass then does another iteration after that operation. Alternatively we could try to move things around immediately, but that is quite hard: those passes already track a lot of state. It is simpler to do the fixup in an entirely separate utility. That does come at the cost of the utility doing another pass on the module and the pass itself running another iteration, but this situation is not the most common.
* [NFC] Refactor ChildLocalizer to handle unreachable code better (#6394)Alon Zakai2024-03-141-7/+2
| | | | | | | | | | | | | | | | This is NFC in the current users, but is necessary functionality for a later PR. ChildLocalizer moves children into locals as needed. It used to stop when it saw the first unreachable. After this change we move such unreachable children out of the parent as well, making this more uniform: all interacting effects are moved out, and all that is left nested in the parent can be moved around and removed as desired. Also add a getReplacement helper that makes using this easier. This cannot be tested comprehensively with the current user as that user will not call this code path on an unreachable parent at all, so this just adds what can be tested. The later PR will have tests for all corner cases.
* DCE: Fix old EH on a pop that gets moved in a catch body (#6400)Alon Zakai2024-03-141-7/+25
|
* [NFC] Clean up the unreachable replacement code in Print.cpp (#6388)Thomas Lively2024-03-081-108/+56
| | | | | | | When instructions cannot be printed because the children from which they are supposed to get their type immediates are unreachable or null, we print blocks of their dropped children followed by unreachables. But the logic for making this happen was more complicated than necessary and in fact included dead code. Clean it up.
* Fix printing of bulk array ops (#6387)Thomas Lively2024-03-081-0/+19
| | | | | | | | | When the bulk array ops had unreachable or null array types, they were replaced with blocks, but not using the correct code that also prints all their children as dropped followed by an unreachable. This meant that the text output in those cases did not parse as a valid module. Fix the bug. A follow-up PR will simplify the code to prevent similar bugs from occurring in the future.
* Print '(offset ...)` in data and element segments (#6379)Thomas Lively2024-03-061-0/+15
| | | | | | | Previously we just printed the offset instruction(s) directly, which is a valid shorthand only when there is a single instruction. In the case of extended constant instructions, there can potentially be multiple instructions, in which case the explicit `offset` clause is required. Print the full clause when necessary.
* Add sourcemap support to wasm-metadce and wasm-merge (#6372)Jérôme Vouillon2024-03-061-3/+1
|
* OptimizeAddedConstants: Replace an assert with a proper error (#6375)Alon Zakai2024-03-041-2/+5
| | | See #6373
* Typed continuations: cont.bind instructions (#6365)Frank Emrich2024-03-042-1/+7
| | | | | | | | | | | | | | | | | | | | | | | | This PR is part of a series that adds basic support for the [typed continuations/wasmfx proposal](https://github.com/wasmfx/specfx). This particular PR adds support for the `cont.bind` instruction for partially applying continuations, documented [here](https://github.com/wasmfx/specfx/blob/main/proposals/continuations/Overview.md#instructions). In short, these instructions are of the form `(cont.bind $ct_before $ct_after)` where `$ct_before` and `$ct_after` are related continuation types. They must only differ in the number of arguments, where `$ct_before` has _n_ additional parameters as compared to `$ct_after`, for some _n_ ≥ 0. The idea is that `(cont.bind $ct_before $ct_after)` then takes a reference to a continuation of type `$ct_before` as well as _n_ operands and returns a (reference to a) continuation of type `$ct_after`. Thus, the folded textual representation looks like `(cont.bind $ct_before $ct_after arg1 ... argn c)`. Support for the instruction is implemented in both the old and the new wat parser. Note that this PR does not implement validation of the new instruction.
* Fuzzer: Mark Roundtrip pass as adding effects (#6366)Alon Zakai2024-02-291-0/+6
|
* [NFC] Add the type of the Expression when eliding it (#6362)Alon Zakai2024-02-281-1/+2
| | | | | | | | | | In some cases we don't print an Expression in full if it is unreachable, so we print something instead as a placeholder. This happens in unreachable code when the children don't provide enough info to print the parent (e.g. a StructGet with an unreachable reference doesn't know what struct type to use). This PR prints out the name of the Expression type of such things, which can help debugging sometimes.
* [NFC] Add some comments about flow in SubtypingDiscoverer and Unsubtyping ↵Alon Zakai2024-02-281-0/+11
| | | | | | | (#6359) I audited all of SubtypingDiscoverer for flow/non-flow constraints and added some comments to clarify things for our future selves if we ever need to generalize it.
* [Outlining] Fixes break reconstruction (#6352)Ashley Nelson2024-02-271-1/+13
| | | Adds new visitBreakWithType and visitSwitchWithType functions to the IRBuilder API. These functions work around an assumption in IRBuilder that the module is being traversed in the fully nested format, i.e., that the destination scope of a break or switch has been visited before visiting the break or switch. Instead, the type of the destination scope is passed to IRBuilder.
* SubtypingDiscoverer: Differentiate non-flow subtyping constraints (#6344)Alon Zakai2024-02-272-0/+20
| | | | | | | | | | | | | | | | | | When we do a local.set of a value into a local then we have both a subtyping constraint - for the value to be valid to put in that local - and also a flow of a value, which can then reach more places. Such flow then interacts with casts in Unsubtyping, since it needs to know what can flow where in order to know how casts force us to keep subtyping relations. That regressed in the not-actually-NFC #6323 in which I added the innocuous lines to add subtyping constraints in ref.eq. It seems fine to require that the arms of a RefEq must be of type eqref, but Unsubtyping then assuming those arms flowed into a location of type eqref... which means casts might force us to not optimize some things. To fix this, differentiate the rare case of non-flowing subtyping constraints, which is basically only RefEq. There are perhaps a few more cases (like i31 operations) but they do not matter in practice for Unsubtyping anyhow; I suggest we land this first to undo the regression and then at our leisure investigate the other instructions.
* [StringLowering] Lower `stringview_wtf16.get_codeunit` to `charCodeAt` (#6353)Thomas Lively2024-02-261-4/+4
| | | | Previously we lowered this to `getCodePointAt`, which has different semantics around surrogate pairs.
* Typed continuations: cont.new instructions (#6308)Frank Emrich2024-02-222-0/+6
| | | | | | | | | | | | | | | | | This PR is part of a series that adds basic support for the [typed continuations/wasmfx proposal](https://github.com/wasmfx/specfx). This particular PR adds support for the `cont.new` instruction for creating continuations, documented [here(https://github.com/wasmfx/specfx/blob/main/proposals/continuations/Overview.md#instructions). In short, these instructions are of the form `(cont.new $ct)` where `$ct` must be a continuation type. The instruction takes a single (nullable) function reference as its argument, which means that the folded representation of the instruction is of the form `(cont.new $ct (foo ...))`. Support for the instruction is implemented in both the old and the new wat parser. Note that this PR does not implement validation of the new instruction.
* [NFC] DeNaN: Avoid calls on constants (#6326)Alon Zakai2024-02-211-3/+3
| | | | | A constant is either fixed up immediately, or does not need a call. This makes us slightly faster in the fuzzer, but does not change behavior as before those calls all ended up doing nothing (as the numbers were not nans).
* Fuzzer: Add a pass to prune illegal imports and exports for JS (#6312)Alon Zakai2024-02-203-0/+90
| | | | | | | | | | | | | | | | | | We already have passes to legalize i64 imports and exports, which the fuzzer will run so that we can run wasm files in JS VMs. SIMD and multivalue also pose a problem as they trap on the boundary. In principle we could legalize them as well, but that is substantial effort, so instead just prune them: given a wasm module, remove any imports or exports that use SIMD or multivalue (or anything else that is not legal for JS). Running this in the fuzzer will allow us to not skip running v8 on any testcase we enable SIMD and multivalue for. (Multivalue is allowed in newer VMs, so that part of this PR could be removed eventually.) Also remove the limitation on running v8 with multimemory (v8 now supports that).
* Fuzzer: Add SIMD support to DeNaN (#6318)Alon Zakai2024-02-201-22/+90
|
* [NFC] Use SubtypingDiscoverer in StringLowering (#6325)Alon Zakai2024-02-201-49/+49
| | | | | | | | This replaces horrible hacks to find which nulls need to switch (from none to noext) with general code using SubtypingDiscoverer. That helper is aware of where each expression is written, so we can find those nulls trivially. This is NFC on existing usage but should fix any remaining bugs with null constants.
* StringLowering: Escape the JSON in the custom section (#6316)Alon Zakai2024-02-201-8/+12
| | | | Also add an end-to-end test using node to verify we can parse the escaped content properly using TextDecoder+JSON.parse.
* SetGlobals: Fix segfault on invalid input (#6321)Nikolay Khitrin2024-02-201-1/+1
|
* StringLowering: Lower nulls in call params (#6317)Alon Zakai2024-02-201-0/+10
|
* StringLowering: Properly handle nullable inputs to StringAs (#6307)Alon Zakai2024-02-141-1/+11
| | | StringAs's output must be non-nullable, so add a cast.
* StringLowering: Fix up nulls written to struct.new fields (#6306)Alon Zakai2024-02-141-16/+36
|
* [NFC] Avoid a warning on an unused var (#6300)Alon Zakai2024-02-141-1/+2
|
* StringLowering: Use an array16 type in its own rec group (#6302)Alon Zakai2024-02-131-9/+25
| | | | | | | | | | | | The input module might use an array of 16-bit elements type that is somewhere in a giant rec group, but that is not valid for imported strings: that array type is now on an import and must match the expected ABI, which is to be in its own personal rec group. The old array16 type remains in the module after this transformation, but all uses of it are replaced with uses of the new array16 type. Also move makeImports to after updateTypes: there are no types to update in the new imports. That does not matter but it can make debugging less pleasant, so improve it.
* StringLowering: Hack around if issue with bottom types (#6303)Alon Zakai2024-02-131-0/+21
| | | | | Replacing the string heap type with extern is dangerous as they do not share top/bottom types. In practice this works out almost everywhere except for a few ifs, which we can fix up as a hack for now.
* StringLowering: Modify string=>extern also in public types (#6301)Alon Zakai2024-02-131-1/+15
| | | | We want to actually remove all stringref appearances, in both public and private types.
* Precompute: Optimize array.len (#6299)Alon Zakai2024-02-121-1/+1
| | | Arrays have immutable length, so we can optimize them like immutable fields.
* [NFC] Add links to specs in StringLowering (#6292)Alon Zakai2024-02-081-0/+4
|