<div dir="ltr"><div>To recap, this is what I was trying to solve:<br><br></div><div>This C code:<br></div><div><br></div><div><span style="font-family:courier new,monospace">int bar(int a, int b, int c, int d, int e, int f);</span><br style="font-family:courier new,monospace">
<br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">int foo(int a, int b, int c, int d, int e )</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">{</span><br style="font-family:courier new,monospace">
<span style="font-family:courier new,monospace"> int x = 3*a;</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace"> return bar3(a,b,c,d,e,x);</span><br style="font-family:courier new,monospace">
<span style="font-family:courier new,monospace">}</span><br style="font-family:courier new,monospace"><br></div><div>Produced the following assembly output:<br></div><div><br><span style="font-family:courier new,monospace">foo:</span><br style="font-family:courier new,monospace">
<span style="font-family:courier new,monospace"> push {r11, lr}</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace"> sub sp, #8</span><br style="font-family:courier new,monospace">
<span style="font-family:courier new,monospace"> bl bar</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace"> add sp, #8</span><br style="font-family:courier new,monospace">
<span style="font-family:courier new,monospace"> pop {r11, pc}</span><br><br><br>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).<br>
After a bit of digging, the following patch seems to take care of it.<br><br></div><div>Basically what happens is:<br></div><div>- the C function in the example doesn't have any local to save<br></div><div>- the only spilled register is LR<br>
- the Prolog/Epilog Inserted calls the target specific ARMFrameLowering::processFunctionBeforeCalleeSavedScan<br></div><div>- 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<br>
</div><div>- inside processFunctionBeforeCalleeSavedScan, there a check: if TargetAlign == 8 && (NumGPRSpills & 1) then we align the stack by pushing one of the _unspilled_ registers.<br><br></div><div>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.<br>
</div><div>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")?<br></div><div><br></div><div>
Any comment?<br><br></div><div>Thanks,<br>Andrea<br></div><div><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">diff -aruN llvm-source/lib/Target/ARM/ARMFrameLowering.cpp llvm-source-new/lib/Target/ARM/ARMFrameLowering.cpp</span><br style="font-family:courier new,monospace">
<span style="font-family:courier new,monospace">--- llvm-source/lib/Target/ARM/ARMFrameLowering.cpp 2013-07-29 10:50:07.000000000 -0700</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">+++ llvm-source-new/lib/Target/ARM/ARMFrameLowering.cpp 2013-10-20 16:33:59.905251552 -0700</span><br style="font-family:courier new,monospace">
<span style="font-family:courier new,monospace">@@ -1313,7 +1313,7 @@</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace"> for (unsigned i = 0, e = UnspilledCS1GPRs.size(); i != e; ++i) {</span><br style="font-family:courier new,monospace">
<span style="font-family:courier new,monospace"> unsigned Reg = UnspilledCS1GPRs[i];</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace"> // Don't spill high register if the function is thumb1</span><br style="font-family:courier new,monospace">
<span style="font-family:courier new,monospace">- if (!AFI->isThumb1OnlyFunction() ||</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">+ if (!AFI->isThumbFunction() ||</span><br style="font-family:courier new,monospace">
<span style="font-family:courier new,monospace"> isARMLowRegister(Reg) || Reg == ARM::LR) {</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace"> MRI.setPhysRegUsed(Reg);</span><br style="font-family:courier new,monospace">
<span style="font-family:courier new,monospace"> if (!MRI.isReserved(Reg))</span><br style="font-family:courier new,monospace"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Oct 15, 2013 at 10:15 AM, Andrea Mucignat <span dir="ltr"><<a href="mailto:andrea@nestlabs.com" target="_blank">andrea@nestlabs.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div>Umesh,<br><br></div>From Target/ARM/ARMRegisterInfo.td, it looks like FP for Thumb should be r7 instead of r11.<br>
<br>// Register classes.<br>//<br>// pc == Program Counter<br>// lr == Link Register<br>
// sp == Stack Pointer<br>// r12 == ip (scratch)<br>// r7 == Frame Pointer (thumb-style backtraces)<br>// r9 == May be reserved as Thread Register<br>// r11 == Frame Pointer (arm-style backtraces)<br>// r10 == Stack Limit<br>
<br></div>Regardless, I'm compiling with -fomit-frame-pointer, so it should not really matter, right?<span class=""><font color="#888888"><br><br>Andrea<br></font></span></div><div> </div></div><div class=""><div class="h5">
<div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Oct 15, 2013 at 8:33 AM, Umesh Kalappa <span dir="ltr"><<a href="mailto:umesh.kalappa0@gmail.com" target="_blank">umesh.kalappa0@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi andrea,<br>R11 treated as frame pointer at arm backend , which is fixed again .<br><br>Thanks<span><font color="#888888"><br>
Umesh</font></span><div><div><br><br>On Tuesday, October 15, 2013, Andrea Mucignat <<a href="mailto:andrea@nestlabs.com" target="_blank">andrea@nestlabs.com</a>> wrote:<br>
> Umesh,<br>> Makes some sort of sense to me, OTOH:<br>> If instead of choosing r11 as a "dummy" to align the stack we had chosen some other register in the range r0-r7 then we could have emitted the PUSH encoding T1 (2 bytes opcode) as opposed to the encoding T2 (which is a 4 bytes opcode).<br>
> A<br>><br>> On Tue, Oct 15, 2013 at 2:59 AM, Umesh Kalappa <<a href="mailto:umesh.kalappa0@gmail.com" target="_blank">umesh.kalappa0@gmail.com</a>> wrote:<br>><br>> Hi Andrea,<br>><br>> That is because the LR is the fixed register as per the<br>
> <a href="http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf" target="_blank">http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf</a><br>> and out_char() function is not the leaf function ,Hence compiler<br>
> tends to save and restore the LR and the save and restore of<br>> register r11 is to align stack for 8 bytes as per ARM EABI.<br>><br>><br>><br>> Thanks<br>><br>> ~Umesh<br>><br>><br>> On Tuesday, October 15, 2013, Umesh Kalappa <<a href="mailto:umesh.kalappa0@gmail.com" target="_blank">umesh.kalappa0@gmail.com</a>> wrote:<br>
>> ---------- Forwarded message ----------<br>>> From: Andrea Mucignat <<a href="mailto:andrea@nestlabs.com" target="_blank">andrea@nestlabs.com</a>><br>>> Date: Tue, Oct 15, 2013 at 7:05 AM<br>>> Subject: [LLVMdev] Unwanted push/pop on Cortex-M.<br>
>> To: <a href="mailto:llvmdev@cs.uiuc.edu" target="_blank">llvmdev@cs.uiuc.edu</a><br>>><br>>><br>>> Hi,<br>>><br>>> I have this code:<br>>><br>>> void platform_putchar(int, char);<br>
>> void out_char( char ch );<br>
>><br>>> void out_char( char ch )<br>>> {<br>>> platform_putchar (0, ch);<br>>> }<br>>><br>>> I'm compiling with the following clang invocation:<br>>><br>>> $ /usr/local/vendor/toolchains/llvm/3.3/armv7m/bin/armv7m-none-eabi-clang<br>
>> -mcpu=cortex-m4 -mfloat-abi=soft -mthumb -nostdinc -ffreestanding<br>>> -ffunction-sections -fdata-sections -fno-exceptions -fno-rtti<br>>> -fomit-frame-pointer -momit-leaf-frame-pointer -nostdinc -v -Os -S -o<br>
>> a.s a.c<br>>> vendor-clang version 3.3 (tags/RELEASE_33/final) (based on LLVM 3.3)<br>>> Target: armv7m-none--eabi<br>>> Thread model: posix<br>>> "/usr/local/vendor-20130805-b8d59d2/toolchains/llvm/3.3/armv7m/bin/armv7m-none-eabi-clang"<br>
>> -cc1 -triple thumbv7em-none--eabi -S -disable-free -main-file-name a.c<br>>> -mrelocation-model static -fmath-errno -mconstructor-aliases<br>>> -target-abi aapcs -target-cpu cortex-m4 -msoft-float -mfloat-abi soft<br>
>> -target-feature +soft-float -target-feature +soft-float-abi<br>>> -target-feature -neon -target-linker-version 2.22<br>>> -momit-leaf-frame-pointer -v -ffunction-sections -fdata-sections<br>>> -coverage-file /tmp/a.s -nostdsysteminc -nobuiltininc -resource-dir<br>
>> /usr/local/vendor-20130805-b8d59d2/toolchains/llvm/3.3/armv7m/bin/../lib/clang/3.3<br>>> -Os -fno-dwarf-directory-asm -fdebug-compilation-dir /tmp<br>>> -ferror-limit 19 -fmessage-length 207 -ffreestanding -mstackrealign<br>
>> -fno-rtti -fno-signed-char -fobjc-runtime=gcc<br>>> -fobjc-default-synthesize-properties -fdiagnostics-show-option<br>>> -fcolor-diagnostics -backend-option -vectorize-loops -o a.s -x c a.c<br>>> clang -cc1 version 3.3 based upon LLVM 3.3 default target armv7m-none-eabi<br>
>> #include "..." search starts here:<br>>> End of search list.<br>>><br>>> $ cat a.s<br>>> .syntax unified<br>>> .eabi_attribute 6, 10<br>>> .eabi_attribute 9, 2<br>
>> .eabi_attribute 10, 5<br>>> .fpu vfpv4<br>>> .eabi_attribute 20, 1<br>>> .eabi_attribute 21, 1<br>>> .eabi_attribute 23, 3<br>>> .eabi_attribute 24, 1<br>>> .eabi_attribute 25, 1<br>
>> .eabi_attribute 44, 1<br>>> .file "a.c"<br>>> .section .text.out_char,"ax",%progbits<br>>> .globl out_char<br>>> .align 2<br>>> .type out_char,%function<br>
>> .code 16<br>>> .thumb_func<br>>> out_char:<br>>> push.w {r11, lr}<br>>> mov r1, r0<br>>> movs r0, #0<br>>> bl platform_putchar<br>>> pop.w {r11, pc}<br>
>> .Ltmp0:<br>>> .size out_char, .Ltmp0-out_char<br>>><br>>> The one question I have is:<br>>> why can't this out_char function be compiled into:<br>>><br>>> out_char:<br>
>> mov r1, r0<br>>> mov r0, #0<br>>> bl platform_putchar<br>>> bx lr<br>>><br>>> What's the clang/llvm module responsible for generating the prologue<br>>> and epilogue for this function?<br>
>> I looked into CodeGen/PrologEpilogInserter, ARMFrameLowering.cpp<br>>> Thumb1FrameLowering.cpp but it's not 100% clear how the code gen<br>>> decides what the stack frame look like.<br>>><br>
>> Here's the -emit-llvm output
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div></div></div>