summaryrefslogtreecommitdiff
path: root/src/passes/GlobalStructInference.cpp
Commit message (Collapse)AuthorAgeFilesLines
* [Wasm GC] Enable various passes in hybrid mode, not just nominal (#5202)Alon Zakai2022-10-311-2/+3
|
* Refactor interaction between Pass and PassRunner (#5093)Thomas Lively2022-09-301-3/+5
| | | | | | | | | | | | | | 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.
* Fix nondeterminism in GlobalStructInference (#5092)Alon Zakai2022-09-281-1/+8
| | | | | We append to vectors of globals in a nondeterministically-ordered loop, which can lead to different orderings of the vectors. This happens quite frequently in very large J2Wasm files it turns out. As a solution, simply sort them after the nondeterministic stage.
* [Wasm GC] Support non-nullable locals in the "1a" form (#4959)Alon Zakai2022-08-311-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | An overview of this is in the README in the diff here (conveniently, it is near the top of the diff). Basically, we fix up nn locals after each pass, by default. This keeps things easy to reason about - what validates is what is valid wasm - but there are some minor nuances as mentioned there, in particular, we ignore nameless blocks (which are commonly added by various passes; ignoring them means we can keep more locals non-nullable). The key addition here is LocalStructuralDominance which checks which local indexes have the "structural dominance" property of 1a, that is, that each get has a set in its block or an outer block that precedes it. I optimized that function quite a lot to reduce the overhead of running that logic after each pass. The overhead is something like 2% on J2Wasm and 0% on Dart (0%, because in this mode we shrink code size, so there is less work actually, and it balances out). Since we run fixups after each pass, this PR removes logic to manually call the fixup code from various places we used to call it (like eh-utils and various passes). Various passes are now marked as requiresNonNullableLocalFixups => false. That lets us skip running the fixups after them, which we normally do automatically. This helps avoid overhead. Most passes still need the fixups, though - any pass that adds a local, or a named block, or moves code around, likely does. This removes a hack in SimplifyLocals that is no longer needed. Before we worked to avoid moving a set into a try, as it might not validate. Now, we just do it and let fixups happen automatically if they need to: in the common code they probably don't, so the extra complexity seems not worth it. Also removes a hack from StackIR. That hack tried to avoid roundtrip adding a nondefaultable local. But we have the logic to fix that up now, and opts will likely keep it non-nullable as well. Various tests end up updated here because now a local can be non-nullable - previous fixups are no longer needed. Note that this doesn't remove the gc-nn-locals feature. That has been useful for testing, and may still be useful in the future - it basically just allows nn locals in all positions (that can't read the null default value at the entry). We can consider removing it separately. Fixes #4824
* Disallow --nominal with GC (#4758)Thomas Lively2022-06-281-0/+3
| | | | | | | | | | | Nominal types don't make much sense without GC, and in particular trying to emit them with typed function references but not GC enabled can result in invalid binaries because nominal types do not respect the type ordering constraints required by the typed function references proposal. Making this change was mostly straightforward, but required fixing the fuzzer to use --nominal only when GC is enabled and required exiting early from nominal-only optimizations when GC was not enabled. Fixes #4756.
* GlobalStructInference: Handle >2 globals if values coincide (#4714)Alon Zakai2022-06-081-14/+80
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In GSI we look for a read of a global in a situation like this: $global1: value1 $global2: value2 (struct.get $Type (ref)) If global inference shows this get must be of either $global1 or $global2, then we can optimize to this: (ref) == $global1 ? value1 : value2 We focus on the case of two values because 1 is handled by other passes, and >2 makes the tradeoffs less clear. However, a simple extension is the case where there are more than 2 globals, but there are only two values, and one value is unique to one global: $global1: valueA $global2: valueB $global3: valueA => (ref) == $global2 ? valueB : valueA We can still use a single comparison here, on the global that has the unique value. Then the else will handle all the other globals. This increases the cases that GSI can optimize J2Wasm output by over 50%.
* Global Struct Inference pass: Infer two constants in struct.get (#4659)Alon Zakai2022-06-011-0/+244
This optimizes constants in the megamorphic case of two: when we know two function references are possible, we could in theory emit this: (select (ref.func A) (ref.func B) (ref.eq (..ref value..) ;; globally, only 2 things are possible here, and one has ;; ref.func A as its value, and the other ref.func B (ref.func A)) That is, compare to one of the values, and emit the two possible values there. Other optimizations can then turn a call_ref on this select into an if over two direct calls, leading to devirtualization. We cannot compare a ref.func directly (since function references are not comparable), and so instead we look at immutable global structs. If we find a struct type that has only two possible values in some field, and the structs are in immutable globals (which happens in the vtable case in j2wasm for example), then we can compare the references of the struct to decide between the two values in the field.