JIT: Fix physical promotion creating overlapping local uses (#91088)
Physical promotion could in some cases create uses overlapping illegally
with defs when faced with seemingly last uses of structs. This is a
result of a mismatch between our model for liveness and the actual model
of local uses in the backend. In the actual model, the uses of LCL_VARs
occur at the user, which means that it is possible for there to be no
place at which to insert IR between to local uses.
The example looks like the following. Physical promotion would be faced
with a tree like
```
▌ CALL void Program:Foo(Program+S,Program+S)
├──▌ LCL_VAR struct<Program+S, 4> V01 loc0
└──▌ LCL_VAR struct<Program+S, 4> V01 loc0
```
When V01 was fully promoted, both of these are logically last uses since
all state of V01 is stored in promoted field locals. Because of that we
would make the following transformation:
```
▌ CALL void Program:Foo(Program+S,Program+S)
├──▌ LCL_VAR struct<Program+S, 4> V01 loc0 (last use)
└──▌ COMMA struct
├──▌ STORE_LCL_FLD int V01 loc0 [+0]
│ └──▌ LCL_VAR int V02 tmp0
└──▌ LCL_VAR struct<Program+S, 4> V01 loc0 (last use)
```
This creates an illegally overlapping use and def; additionally, it is
correct only in a world where the store actually would happen between
the two uses. It is also moderately dangerous to mark both of these as
last uses given the implicit byref transformation.
The fix is to avoid marking a struct use as a last use if we see more
struct uses in the same statement.
Fix #91056
Co-authored-by: Jakob Botsch Nielsen <jakob.botsch.nielsen@gmail.com>