title: Why does GCC generates Fxxx instead of Vxxx floating point assembly instructions for Cortex-A9?
body: <p>I'm trying to generate floating point code for the ARM Cortex-A9. I am investigating the performance difference between code generated for the NEON coprocessor versus code generated only for the VFPV3 coprocessor. I started with the following simple test program:</p>
  
  <pre><code>#define ASIZE 4
  
  float   A[ASIZE] = {7.0f, 2.0f, 3.0f, 4.0f};
  float   B[ASIZE] = {5.0f, 6.0f, 7.0f, 8.0f};
  float   C[ASIZE];
  
  int main(void) {
  unsigned int i;
  for (i=0; i&lt;ASIZE; i++)
  {
      C[i] = A[i] + B[i];
  }
  return 0;
  }
  </code></pre>
  
  <p>When I compile it with the following flags</p>
  
  <pre><code>CCFLAGS = -g -c -O3 -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp -ffast-math -funsafe-math-optimizations 
  </code></pre>
  
  <p>I get the following assembly output from either GCC or Code Sourcery Lite compilers:</p>
  
  <pre><code> 9:atest.c       **** int main(void) {
  23                      .loc 1 9 0
  24                      .cfi_startproc
  25                      @ args = 0, pretend = 0, frame = 0
  26                      @ frame_needed = 0, uses_anonymous_args = 0
  27                      @ link register save eliminated.
  10:atest.c       **** 
  11:atest.c       ****   unsigned int i;
  12:atest.c       **** 
  13:atest.c       ****   for (i=0; i&lt;ASIZE; i++)
  14:atest.c       ****   {
  15:atest.c       ****       C[i] = A[i] + B[i];
  28                      .loc 1 15 0
  29 0000 003000E3        movw    r3, #:lower16:.LANCHOR0
  30 0004 002000E3        movw    r2, #:lower16:C
  31 0008 003040E3        movt    r3, #:upper16:.LANCHOR0
  32 000c DF2A63F4        vld1.64 {d18-d19}, [r3:64]
  33 0010 040BD3ED        vldr    d16, [r3, #16]
  34 0014 061BD3ED        vldr    d17, [r3, #24]
  35 0018 E00D42F2        vadd.f32    q8, q9, q8
  36 001c 002040E3        movt    r2, #:upper16:C
  16:atest.c       ****   }
  17:atest.c       **** 
  18:atest.c       ****   return 0;
  19:atest.c       **** }
  </code></pre>
  
  <p>This is what I expected to see. The float point instructions are in the form of "Vxxx".</p>
  
  <p>Now when I change the compiler flag to -mfpu=vfpv3 (or any other permutation such as -mfpu=vfpv3-d16-f16) I see the following:</p>
  
  <pre><code> 9:atest.c       **** int main(void) {
  23                      .loc 1 9 0
  24                      .cfi_startproc
  25                      @ args = 0, pretend = 0, frame = 0
  26                      @ frame_needed = 0, uses_anonymous_args = 0
  27                      @ link register save eliminated.
  28                  .LVL0:
  11:atest.c       ****   unsigned int i;
  13:atest.c       ****   for (i=0; i&lt;ASIZE; i++)
  14:atest.c       ****   {
  15:atest.c       ****       C[i] = A[i] + B[i];
  29                      .loc 1 15 0
  30 0000 003000E3        movw    r3, #:lower16:.LANCHOR0
  31 0004 002000E3        movw    r2, #:lower16:C
  32 0008 003040E3        movt    r3, #:upper16:.LANCHOR0
  33 000c 002040E3        movt    r2, #:upper16:C
  34 0010 004A93ED        flds    s8, [r3]
  16:atest.c       ****   }
  18:atest.c       ****   return 0;
  19:atest.c       **** }
  35                      .loc 1 19 0
  36 0014 0000A0E3        mov r0, #0
  15:atest.c       ****   }
  37                      .loc 1 15 0
  38 0018 046A93ED        flds    s12, [r3, #16]
  39 001c 014AD3ED        flds    s9, [r3, #4]
  40 0020 056AD3ED        flds    s13, [r3, #20]
  41 0024 025A93ED        flds    s10, [r3, #8]
  42 0028 067A93ED        flds    s14, [r3, #24]
  43 002c 035AD3ED        flds    s11, [r3, #12]
  44 0030 077AD3ED        flds    s15, [r3, #28]
  45 0034 066A34EE        fadds   s12, s8, s12
  46 0038 A66A74EE        fadds   s13, s9, s13
  47 003c 077A35EE        fadds   s14, s10, s14
  48 0040 A77A75EE        fadds   s15, s11, s15
  49 0044 006A82ED        fsts    s12, [r2]
  50                  .LVL1:
  51 0048 016AC2ED        fsts    s13, [r2, #4]
  52                  .LVL2:
  53 004c 027A82ED        fsts    s14, [r2, #8]
  54                  .LVL3:
  55 0050 037AC2ED        fsts    s15, [r2, #12]
  56                  .LVL4:
  57                      .loc 1 19 0
  58 0054 1EFF2FE1        bx  lr
  59                      .cfi_endproc
  60                  .LFE0:
  61                      .fnend
  </code></pre>
  
  <p>All the floating point assembly instructions are in the form "Fxxx". Why aren't they in the form "Vxxx"?  I was expecting to see load instructions that looked like VLD1.32 and add instructions that looked like VADD.F32. When I searched for the instruction "flds" in the official ARM documentation it says that "flds" was used on the ARM9 architecture, not Cortex-A9.</p>
  
  <p>I have tried every combination of -mcpu, -mfpu, -march compiler flags, but I can't seem to generate floating point assembly instructions in the form "Vxxx" using either the GCC compiler for Linux or the Code Sorcery Lite compiler for Linux. What am I doing wrong?</p>