[PATCH] D42535: [ARM] Accept a subset of Thumb GPR register class when emitting an SP-relative load instruction
Momchil Velikov via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 25 06:59:26 PST 2018
chill created this revision.
chill added reviewers: rengolin, efriedma.
Herald added subscribers: kristof.beyls, javed.absar, aemerson.
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).
Repository:
rL LLVM
https://reviews.llvm.org/D42535
Files:
lib/Target/ARM/Thumb1InstrInfo.cpp
test/CodeGen/ARM/v8m-tail-call.ll
Index: test/CodeGen/ARM/v8m-tail-call.ll
===================================================================
--- test/CodeGen/ARM/v8m-tail-call.ll
+++ test/CodeGen/ARM/v8m-tail-call.ll
@@ -103,3 +103,28 @@
}
declare i32 @bar(i32, i32, i32, i32)
+
+; Regression test for failure to load indirect branch target (class tcGPR) from
+; a stack slot.
+%struct.S = type { i32 }
+
+define void @test8(i32 (i32, i32, i32)* nocapture %fn, i32 %x) local_unnamed_addr {
+entry:
+ %call = tail call %struct.S* bitcast (%struct.S* (...)* @test8_u to %struct.S* ()*)()
+ %a = getelementptr inbounds %struct.S, %struct.S* %call, i32 0, i32 0
+ %0 = load i32, i32* %a, align 4
+ %call1 = tail call i32 @test8_h(i32 0)
+ %call2 = tail call i32 @test8_g(i32 %0, i32 %call1, i32 0)
+ store i32 %x, i32* %a, align 4
+ %call4 = tail call i32 %fn(i32 1, i32 2, i32 3)
+ ret void
+}
+
+declare %struct.S* @test8_u(...)
+
+declare i32 @test8_g(i32, i32, i32)
+
+declare i32 @test8_h(i32)
+; CHECK: str r0, [sp] @ 4-byte Spill
+; CHECK: ldr r3, [sp] @ 4-byte Reload
+; CHECK: bx r3
Index: lib/Target/ARM/Thumb1InstrInfo.cpp
===================================================================
--- lib/Target/ARM/Thumb1InstrInfo.cpp
+++ lib/Target/ARM/Thumb1InstrInfo.cpp
@@ -109,11 +109,11 @@
unsigned DestReg, int FI,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
- assert((RC == &ARM::tGPRRegClass ||
+ assert((RC->hasSuperClassEq(&ARM::tGPRRegClass) ||
(TargetRegisterInfo::isPhysicalRegister(DestReg) &&
isARMLowRegister(DestReg))) && "Unknown regclass!");
- if (RC == &ARM::tGPRRegClass ||
+ if (RC->hasSuperClassEq(&ARM::tGPRRegClass) ||
(TargetRegisterInfo::isPhysicalRegister(DestReg) &&
isARMLowRegister(DestReg))) {
DebugLoc DL;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D42535.131442.patch
Type: text/x-patch
Size: 1863 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180125/5d70a1f4/attachment-0001.bin>
More information about the llvm-commits
mailing list