This is an archive of the discontinued LLVM Phabricator instance.

[mips] Reserve $at and use it for frame pointer elimination.
AbandonedPublic

Authored by vstefanovic on Dec 3 2014, 11:21 AM.

Details

Reviewers
dsanders
petarj
Summary

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.

Diff Detail

Event Timeline

vstefanovic retitled this revision from to [mips] Reserve $at and use it for frame pointer elimination..
vstefanovic updated this object.
vstefanovic edited the test plan for this revision. (Show Details)
vstefanovic added reviewers: dsanders, petarj.
vstefanovic set the repository for this revision to rL LLVM.
vstefanovic added a subscriber: Unknown Object (MLST).

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

dsanders edited edge metadata.Dec 4 2014, 2:25 AM

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.