[AArch64] Allocate two emergency spill slots for MTE to fix register … (#186505)
…scavenger crash
When `-sanitize=memtag-stack` is enabled and the compiler optimizes
contiguous ST2Gi instructions into an MTE loop (via
`TagStoreEdit::emitLoop`), it spawns two new post-RA virtual registers
simultaneously:
1. `BaseReg`
2. `SizeReg`
Under extremely high register pressure (such as in Swift async
continuation thunks, where almost all registers are kept live), the
Register Scavenger must fall back to using emergency spill slots to
assign physical registers to `BaseReg` and `SizeReg`.
Prior to this patch, `determineCalleeSaves` assumed that a maximum of
one register would ever need to be scavenged at a time. It either
allocated a single emergency spill slot, or bypassed the allocation
entirely if it found an unused Callee-Saved Register (`ExtraCSSpill`) to
use as a scratch register.
When the MTE loop asks for two registers simultaneously, the scavenger
crashes with:
`LLVM ERROR: Error while trying to spill LR from class GPR64: Cannot
scavenge register without an emergency spill slot!`
This patch fixes the crash by explicitly searching for mergeable STG
instructions during `determineCalleeSaves`. If found, it allocates a
second emergency spill slot. This guarantees the scavenger has enough
slots to successfully resolve both post-RA virtual registers, regardless
of whether the first scratch space came from an `ExtraCSSpill` or the
baseline emergency spill slot.
Added `memtag-emergency-spill-slot.mir` to test both the `ExtraCSSpill`
bypass path and the baseline zero-free-register path.
Assisted-by: claude
rdar://172501087