[cfe-users] ARM fast interrupt handlers
Sven Köhler
sven.koehler at gmail.com
Mon Mar 2 09:39:51 PST 2015
Hi,
clang/llvm 3.5 was generating bad assembly code for FIQ interrupt
handlers when optimization was enabled. Now with llvm 3.6 the generated
assembly seems to be working, but it's somewhat suboptimal.
If this is not the right place to discuss, please let me know what might
be a better place.
First consider this C-code:
int* global;
__attribute__((interrupt("IRQ")))
void irq() {
*global++ = 1;
}
__attribute__((interrupt("FIQ")))
void fiq() {
*global++ = 1;
}
I'm generating the assembly like this:
clang --target=armv7-linux-gnu -mfloat-abi=hard -O2 -S
With llvm 3.5.0 I got severely broken code for fiq():
fiq:
movw r8, :lower16:global
subs pc, lr, #4
movt r8, :upper16:global
ldr r9, [r8]
add r10, r9, #4
str r10, [r8]
mov r8, #1
str r8, [r9]
The jump that exits the function basically was "optimized" to the
beginning of the function. The resulting could would basically not do
anything. With -O0, the generated assembly was fine.
Now with llvm 3.6.0, the code is a bit more "lengthy" but correct:
fiq:
push {r11}
mov r11, sp
sub sp, sp, #4
bfc sp, #0, #3
movw r8, :lower16:global
movt r8, :upper16:global
ldr r9, [r8]
add r10, r9, #4
str r10, [r8]
mov r8, #1
str r8, [r9]
mov sp, r11
pop {r11}
subs pc, lr, #4
For some reason, clang sets up the frame pointer register (r11). All of
the code busy with managing r11 could be omitted. Not sure what the bfc
command does. Does it try to round down sp to a multiple of four? Even
though the stack has already been used by the push? Push probably
doesn't support unaligned access. And sp is actually never ever used.
The assembly generated for irq() is somewhat similar. Only the assembly
generated for normal() doesn't bother about r11 and looks quite optimal.
I tried using -fomit-frame-pointer, but it didn't improve the assembly.
Any ideas what's going on?
Regards,
Sven
More information about the cfe-users
mailing list