Repository navigation
Conversation
| // Heap2Local cannot optimize this due to the overlapping live ranges (it sees | ||
| // the x.value operations are not exclusive to any single allocation). But this | ||
| // pass can optimize into this: |
There was a problem hiding this comment.
The reason Heap2Local can't handle this is because it only analyzes a single allocation at a time, rather than doing a single analysis phase covering all allocations in the function. This design limitation is also responsible for significant additional complexity in the pass. Have you experimented with fixing Heap2Local to analyze all allocations at once?
There was a problem hiding this comment.
Yes,
Handling live ranges, sort of like liveness of locals for register allocation / local coalescing, is possible, but quite complex
I had Gemini get this fully working, then simplify as much as it (and I) could, and it was... not pretty.
Basically you need to layer an additional LivenessAnalysis in Heap2Local, just adding a lot of complexity. Sadly it can't replace any existing part. It is even harder than a normal locals-based liveness because we must track allocations as they live in locals, but also as they flow - e.g. two allocations flowing through arms of the same If.
Our main escape analysis pass, Heap2Local, does not handle overlapping
live ranges, things like this:
More than one allocation is being read from in those
x.valueoperations,so Heap2Local sees the uses are not "exclusive", and it gives up.
Handling live ranges, sort of like liveness of locals for register allocation /
local coalescing, is possible, but quite complex. However, the pattern
above can be optimized in another way, which this new pass handles:
when the reference is always read from (using
struct.get, which is the.valueoperations above), then we can just shift from using the referenceto using data:
We store the data in a new local
x_value, and that is all we need.That is, this pass handles a situation that is more restricted than
Heap2Local, in that it doesn't do complex analysis of control flow
and handling of
ref.eqand such, but it is more general in that itcan handle overlapping live ranges in a trivial way.
Fixes #8641 , a Dart testcase, and I saw this helps real-world binaries from
Kotlin and Java too - this is a common pattern.