At various points in the post-isel optimisation passes, instructions get rewritten and replaced. One way to handle this is just to transfer the instruction number from the old to the new instruction -- however that doesn't account for passes like TwoAddressInstruction, which change the positions of operands. Instead:
- We never re-use instruction numbers: when a new instruction is created, it gets a new number,
- This patch adds a table of "substitutions": a mapping from old <inst,operand> pairs to the new ones.
This stems from patch 1 in this series: there's no connection between instruction numbers and DBG_INSTR_REFs preserved.
The downside of this is that we end up preserving in memory a mapping table, which more or less contains the history of optimisations that have happened to the function; and we have to apply the substitutions later, when LiveDebugValues runs. IMO this is a worthy price to pay, one table isn't highly expensive, and it models the way I'd like variable location tracking to work, doing as little work as possible during compilation and resolving variables back to locations at the end.
An additional benefit of changing instruction numbers when the instruction is recreated / modified is that changes which destroy the creator of a value can be expressed, by not creating a substitution for the old <inst,operand> pair. An example would be, if there were a divide instruction that generated the quotient and remainder, and it were replaced by one that only generated the quotient:
$rax, $rcx = div-and-remainder $rdx, $rsi, debug-instr-num 1 DBG_INSTR_REF 1, 0 DBG_INSTR_REF 1, 1
$rax = div $rdx, $rsi, debug-instr-num 2 DBG_INSTR_REF 1, 0 DBG_INSTR_REF 1, 1
With a substitution entered from <1, 0> to <2, 0>, and no substitution created for <1, 1> as it's no longer generated.
This patch only adds the data structure and MIR format, plus round-trip test.