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

Reply via email to