title: GCC SSE code optimization
body: <p>This post is closely related to another one I posted <a href="https://stackoverflow.com/questions/7014018/sse-performance">some days ago</a>. This time, I wrote a simple code that just adds a pair of arrays of elements, multiplies the result by the values in another array and stores it in a forth array, all variables floating point double precision typed. </p>
  
  <p>I made two versions of that code: one with SSE instructions, using calls to and another one without them I then compiled them with gcc and -O0 optimization level. I write them below:</p>
  
  <pre><code>// SSE VERSION
  
  #define N 10000
  #define NTIMES 100000
  #include &lt;time.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;xmmintrin.h&gt;
  #include &lt;pmmintrin.h&gt;
  
  double a[N] __attribute__((aligned(16)));
  double b[N] __attribute__((aligned(16)));
  double c[N] __attribute__((aligned(16)));
  double r[N] __attribute__((aligned(16)));
  
  int main(void){
    int i, times;
    for( times = 0; times &lt; NTIMES; times++ ){
       for( i = 0; i &lt;N; i+= 2){ 
          __m128d mm_a = _mm_load_pd( &amp;a[i] );  
          _mm_prefetch( &amp;a[i+4], _MM_HINT_T0 );
          __m128d mm_b = _mm_load_pd( &amp;b[i] );  
          _mm_prefetch( &amp;b[i+4] , _MM_HINT_T0 );
          __m128d mm_c = _mm_load_pd( &amp;c[i] );
          _mm_prefetch( &amp;c[i+4] , _MM_HINT_T0 );
          __m128d mm_r;
          mm_r = _mm_add_pd( mm_a, mm_b );
          mm_a = _mm_mul_pd( mm_r , mm_c );
          _mm_store_pd( &amp;r[i], mm_a );
        }   
     }
   }
  
  //NO SSE VERSION
  //same definitions as before
  int main(void){
    int i, times;
     for( times = 0; times &lt; NTIMES; times++ ){
       for( i = 0; i &lt; N; i++ ){
        r[i] = (a[i]+b[i])*c[i];
      }   
    }
  }
  </code></pre>
  
  <p>When compiling them with -O0, gcc makes use of XMM/MMX registers and SSE intstructions, if not specifically given the -mno-sse (and others) options. I inspected the assembly code generated for the second code and I noticed that it makes use of <i>movsd</i>, <i>addsd</i> and <i>mulsd</i> instructions. So it makes use of SSE instructions but only of those that use the lowest part of the registers, if I am not wrong. The assembly code generated for the first C code made use, as expected, of the <i>addp</i> and <i>mulpd</i> instructions, though a pretty larger assembly code was generated. </p>
  
  <p>Anyway, the first code should get better profit, as far as I know, of SIMD paradigm, since every iteration two result values are computed. Still that, the second code performs something such as a 25 per cent faster than the first one. I also made a test with single precision values and get similar results. What's the reason for that?</p>