To recap, this is what I was trying to solve:
This C code:
int bar(int a, int b, int c, int d, int e, int f);
int foo(int a, int b, int c, int d, int e )
{
int x = 3*a;
return bar3(a,b,c,d,e,x);
}
Produced the following assembly output:
foo:
push {r11, lr}
sub sp, #8
bl bar
add sp, #8
pop {r11, pc}
The part I didn’t like is that push/pop become 4 bytes instructions because the register that we picked to “align” the stack pointer does not belong to the low register set (r0-r7).
After a bit of digging, the following patch seems to take care of it.
Basically what happens is:
-
the C function in the example doesn’t have any local to save
-
the only spilled register is LR
-
the Prolog/Epilog Inserted calls the target specific ARMFrameLowering::processFunctionBeforeCalleeSavedScan
-
at this point the we need to fix the fact that SP would not be EABI compliant because only 1 register has been spilled so far
-
inside processFunctionBeforeCalleeSavedScan, there a check: if TargetAlign == 8 && (NumGPRSpills & 1) then we align the stack by pushing one of the unspilled registers.
The problem is that this “unspilled” register list starts with r11 (for reasons I’m not clear about), so I decided to skip all the registers r8-r15.
The part I’m not sure about is: what if r4-r7 are all spilled already, is the SP going to be aligned by some other routine later on (maybe by adding a “sub sp, sp, #4”)?
Any comment?
Thanks,
Andrea
diff -aruN llvm-source/lib/Target/ARM/ARMFrameLowering.cpp llvm-source-new/lib/Target/ARM/ARMFrameLowering.cpp
— llvm-source/lib/Target/ARM/ARMFrameLowering.cpp 2013-07-29 10:50:07.000000000 -0700
+++ llvm-source-new/lib/Target/ARM/ARMFrameLowering.cpp 2013-10-20 16:33:59.905251552 -0700
@@ -1313,7 +1313,7 @@
for (unsigned i = 0, e = UnspilledCS1GPRs.size(); i != e; ++i) {
unsigned Reg = UnspilledCS1GPRs[i];
// Don’t spill high register if the function is thumb1
- if (!AFI->isThumb1OnlyFunction() ||
- if (!AFI->isThumbFunction() ||
isARMLowRegister(Reg) || Reg == ARM::LR) {
MRI.setPhysRegUsed(Reg);
if (!MRI.isReserved(Reg))