Function:
float y;
float foo(float x)
{
y = x * x + x;
asm volatile ("vmov.i8 q0, #0" ::: "q0");
asm volatile ("vmov.i8 q1, #0" ::: "q1");
asm volatile ("vmov.i8 q2, #0" ::: "q2");
asm volatile ("vmov.i8 q3, #0" ::: "q3");
asm volatile ("vmov.i8 q4, #0" ::: "q4");
asm volatile ("vmov.i8 q5, #0" ::: "q5");
asm volatile ("vmov.i8 q6, #0" ::: "q6");
asm volatile ("vmov.i8 q7, #0" ::: "q7");
return y;
}
being compiled with "-O -Wall -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp"
always returns 0.
The cause of incorrect behaviour is that in function foo y is allocated on s15
which is not considered clobbered by "asm volatile ("vmov.i8 q3, #0" :::
"q3");". Mentioning in clobber lists s1 s2 and s3 alongside q0, s5 s6 and s7
alongside q1 and so on solves the problem: clobbered register got spilled.
Omitting any of them makes GCC allocate y on this register and do not spill it.
I also noticed that only d8, d10, d12 and d14 got saved at the beginning of the
function though all d8-d15 should be saved. This was mentioned in bug #42321
comment #1 also.
I tried this example on 4.4.3 and today's trunk.
--
Summary: Overwriting neon quad register does not clobber all
included single registers
Product: gcc
Version: 4.5.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: batuzovk at ispras dot ru
GCC target triplet: arm-unknown-linux-gnueabi
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43440