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