This patch adds another dataflow analysis to the AssignmentTrackingAnalysis pass (though it is much simpler than D136320).
The problem and goal
Disjoint and adjacent fragments compose well, however in the back-end, the following sequence
- dbg.value ... Fragment(0, 64)
- dbg.value ... Fragment(0, 32)
is effectively interpreted as setting Fragment(32, 32) (bits [32, 64)) to undef. Perhaps this scenario is uncommon or doesn't present much of an issue currently. However, this is a problem for assignment tracking where overlapping fragments are common between memory location definitions.
The goal of this analysis is to add new variable location definitions that preserve the "bits in memory" at subsequent definitions.
Dataflow high level details
Similar to the "core" analysis, this is a fixed point dataflow analysis. The main difference is that instead of working with join-semilattice types (monotonic increase to a fixed point) it works with meet-semilattice types (monotonic decrease to a fixed point). Basically, instead of performing something like a union when merging predecessor "live-outs" this one performs something like an intersect.
Implementation details
The value computed for each block is a map of aggregate variable to fragment memory locations. The fragment locations are tracked using an IntervalMap (one for each aggregate variable). The values mapped in the IntervalMaps are IDs that represent a stack slot.
In this patch it's probably easier to start looking at process first then join.
In process the location defs - generated by the first analysis - in each block are iterated over. At each location def for a fragment the relevant IntervalMap is updated. A new interval is inserted and new memory location defs for all partially overlapped intervals that are in memory are saved into BBInsertBeforeMap such that the not-overlapped bits in memory get a new def. For example:
Before: var x bits 0 to 63: value in memory some instructions var x bits 0 to 31: value is %0 After: var x bits 0 to 63: value in memory some instructions var x bits 0 to 31: value is %0 var x bits 32 to 61: value in memory ; <-- new location definition
In join we perform an intersect-like operation on the IntervalMaps. Essentially, we keep only the (sections of) the intervals where all predecessors agree the memory location is in use.
Again, tests coming in another patch.