title: Fast byte-wise replace if
body: <p>I have a function that copies binary data from one area to another, but only if the bytes are different from a specific value. Here is a code sample:</p>
  
  <pre><code>void copy_if(char* src, char* dest, size_t size, char ignore)
  {
    for (size_t i = 0; i &lt; size; ++i)
    {
      if (src[i] != ignore)
        dest[i] = src[i];
    }
  }
  </code></pre>
  
  <p>The problem is that this is too slow for my current need. Is there a way to obtain the same result in a faster way?</p>
  
  <p><strong>Update:</strong>
  Based on answers I tried two new implementations:</p>
  
  <pre><code>void copy_if_vectorized(const uint8_t* src, uint8_t* dest, size_t size, char ignore)
  {
      for (size_t i = 0; i &lt; size; ++i)
      {
          char temps = src[i];
          char tempd = dest[i];
          dest[i] = temps == ignore ? tempd : temps;
      }
  }
  
  void copy_if_SSE(const uint8_t* src, uint8_t* dest, size_t size, uint8_t ignore)
  {
      const __m128i vignore = _mm_set1_epi8(ignore);
  
      size_t i;
  
      for (i = 0; i + 16 &lt;= size; i += 16)
      {
          __m128i v = _mm_loadu_si128((__m128i *)&amp;src[i]);
          __m128i vmask = _mm_cmpeq_epi8(v, vignore);
          vmask = _mm_xor_si128(vmask, _mm_set1_epi8(-1));
          _mm_maskmoveu_si128(v, vmask, (char *)&amp;dest[i]);
      }
      for (; i &lt; size; ++i)
      {
          if (src[i] != ignore)
              dest[i] = src[i];
      }
  
  }
  </code></pre>
  
  <p>And I got the following results:</p>
  
  <pre><code>Naive: 
  Duration: 2.04844s
  Vectorized: 
  Pass: PASS
  Duration: 3.18553s
  SIMD: 
  Pass: PASS
  Duration: 0.481888s
  </code></pre>
  
  <p>I guess my compiler failed to vectorized (last MSVC), but the SIMD solution is good enough, thanks!</p>
  
  <p><strong>Update (bis)</strong>
  I managed to vectorized it using some pragma instructions for my compile (MSVC) and indeed it is actually faster that SIMD, here is the final code:</p>
  
  <pre><code>void copy_if_vectorized(const uint8_t* src, uint8_t* dest, size_t size, char ignore)
  {
  
  #pragma loop(hint_parallel(0))
  #pragma loop(ivdep)
  
  for (int i = 0; i &lt; size; ++i) // Sadly no parallelization if i is unsigned, but more than 2Go of data is very unlikely
  {
      char temps = src[i];
      char tempd = dest[i];
      dest[i] = temps == ignore ? tempd : temps;
  }
  }
  </code></pre>