When spilling a register, RegScavenger calls MipsSERegisterInfo::eliminateFI(),
which needs a free register to handle offsets over 16 bits, resulting in
"Cannot scavenge register without an emergency spill slot!" assert.
This patch puts $at on the reserved registers list, and uses it in eliminateFI()
instead of requesting a register from RegScavenger.
Details
Diff Detail
Event Timeline
When RegScavenger runs out of registers, it tries to spill one. So it generates
e.g.
SW %RA<kill>, <fi#11>, 0
which is converted by eliminateFI() into:
SW %RA<kill>, %FP, Offset
for offsets that fit into 16 bits. Otherwise, we need yet another register:
%vreg79<def> = LUi 1
%vreg79<def> = ADDu %FP, %vreg79<kill>
SW %RA<kill>, %vreg79<kill>, 120
Then RegScavenger is called to provide a register for vreg79, so it asserts with
"Cannot scavenge register without an emergency spill slot!".
There is a number of mips tests that fail when $at is reserved, because they
have hardcoded expected register values, and will have to be fixed if this
patch gets accepted.
Minimal c code to reproduce the error, used to generate vector-multiply.ll
from the patch:
#include <stdint.h>
typedef int8_t VI8 attribute((vector_size(16)));
int main(int argc, char** argh) {
VI8 v0 = (VI8) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; VI8 v1 = (VI8) {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int unused_variable[16384]; VI8 result = v0*v1; return 0;
}
Built with:
clang -S -emit-llvm vector-multiply.c -o vector-multiply.ll -O0
This patch unconditionally reserves a register in order to support the fairly rare case of a stack frame being larger than 64KB. My starting position is that this isn't the right thing to do
Why not create an emergency spill slot for the register scavenger to use when the stack frame is large? This should allow it to cope with this rare case without limiting the optimization of the common cases.