Files
llvm-project/llvm/lib/CodeGen/InlineSpiller.cpp
Quentin Colombet 2774ab189b [InlineSpiller] Fix live-range update in hoisting within bb (#193880)
The InlineSpiller tries to shorten the live-ranges used when storing a
value that is defined by a sibling register by performing the following
transformation:
```
a = copy b
store a
```
=>
```
store b
```
That is, it eliminates the copy and store the original value at the copy
location.

As far as `b`'s live-range is concerned, this transformation is neutral
as long as the store is inserted in place of the copy being removed.

That doesn't hold when the copy is part of the basic block prologue. In
that case, the earliest insertion point for the store is after the
prologue:
```
a = copy b # part of bb prologue
... # more prologue instrs
store a <-- earliest insertion point
```
Therefore when this optimization kicks in and the copy is in the bb's
prologue, b's live-range needs to be extended to that insertion point.

This is exactly what this fix does.

Note: This issue is fairly easy to understand from an IR stand point and
one would expect a small reproducer.
Indeed, we would need only something that looks like:
```
a = copy b # prologue compatible copy
... # some more prologue instrs
... # high pressure point
= use a
```

The problem is the InlineSpiller optimization (implemented in
InlineSpiller::hoistSpillInsideBB) triggers only if `a` and `b` are
sibling registers, meaning they are the product of a live-range
splitting. Controlling live-range splitting is hard and I couldn't come
up with a smaller test case. The problem also disappears if we run
greedy alone because the live-ranges are repacked (well the slot indices
to be exact) compared to what the scheduler produces. That changes the
allocation order and the bug is not hit anymore.
The alternative would be to run the pipeline from the
coalescer/scheduler but that's not a whole lot more robust than the LLVM
IR path, plus the reproducer would be ~20k line long!

The other option (maybe something we should do in the long term) would
be to serialize/deserialize the VirtRegMap object so that we can set the
Virt2SplitMap map in a state that register a and b as siblings.
2026-04-27 16:42:16 -07:00

69 KiB