This is an archive of the discontinued LLVM Phabricator instance.

[ARM] Accept a subset of Thumb GPR register class when emitting an SP-relative load instruction
ClosedPublic

Authored by chill on Jan 25 2018, 6:59 AM.

Details

Summary

Compiling the following program with -target arm-eabi -mcpu=cortex-m23 -O2

struct S {
    int a;
};

extern struct S *test8_u();
extern int test8_g(int, int, int);
extern int test8_h(int);

void test8(int (*fn)(int, int, int), int x) {
    struct S *p = test8_u();
    test8_g(p->a, test8_h(0), 0);
    p->a = x;
    fn(1, 2, 3);
}

results in internal compiler error ran out of registers during register allocation.

We have the function pointer spilled on the stack. When the compiler tries to load
it into a register, it creates a virtual register of class tGPR, which is the operand
class of the destination operand in the load instruction. This virtual register, though,
is also used by a TCRETURN instruction, which requires register class tcGPR, so
the destination of the load becomes tcGPR_and_tGPR. However,
Thumb1InstrInfo::loadRegFromStackSlot accepts only the tGPR register
class. The latter function server to emit a tLDRspi instruction and certainly any
subset of the tGPR register class is a valid destination of the load.

(The class tcGPR_and_tGPR can be also a result of register coalescing).

Diff Detail

Repository
rL LLVM

Event Timeline

chill created this revision.Jan 25 2018, 6:59 AM
This revision is now accepted and ready to land.Jan 25 2018, 11:57 AM
This revision was automatically updated to reflect the committed changes.