title: OpenMP declare SIMD for an inline function
body: <p>The <a href="http://www.openmp.org/mp-documents/openmp-4.5.pdf#subsection.2.8.2" rel="nofollow noreferrer">current OpenMP standard</a> says about the <code>declare simd</code> directive for C/C++:</p>
  
  <blockquote>
    <p>The use of a declare simd construct on a function enables the creation
    of SIMD versions of the associated function that can be used to
    process multiple arguments from a single invocation in a SIMD loop
    concurrently.</p>
  </blockquote>
  
  <p>More details are given in the chapter, but there seems to be no restriction there to the type of function the directive can be applied to.</p>
  
  <p>So my question is, can this directive be applied safely to an <code>inline</code> function?</p>
  
  <p>I'm asking that for two reasons:</p>
  
  <ol>
  <li>An <code>inline</code> function is a rather unusual function, since it is normally inlined directly in the place it was called. So it is likely never compiled as a standalone function and therefore, the <code>declare simd</code> aspect of it is quite redundant with the possible <code>simd</code> directive at the enclosing loop's level.</li>
  <li>I have a code with such <code>inline</code> <code>declare simd</code> functions, and sometimes, for some nebulous reasons, GCC complains about their multiple definition at link time (with names mangled with extra characters suggesting that these are vectorised versions). But if I remove the <code>declare simd</code> directive, it compiles and link fine.</li>
  </ol>
  
  <p>So far I hadn't think too much about it, but now I'm puzzled. Is that a bug of mine (ie using <code>declare simd</code> for <code>inline</code> functions) or is that a problem in GCC generating binary vectorised versions of <code>inline</code> functions and failing to sort them out at link time?</p>
  
  <hr>
  
  <p><strong>EDIT:</strong><br>
  There is a GCC compiler options which makes a difference. When the inlining is enabled (with <code>-O3</code> for example), the code compiles and links fine. But when compiled with <code>-O0</code> or with <code>-O3 -fno-inline</code>, the inlining is disabled and the linking fails with this "multiple definition of" the function decorated with the <code>omp declare simd</code> directive.</p>
  
  <hr>
  
  <p><strong>EDIT 2:</strong><br>
  Thanks to @Zboson questions regarding the compiler flags, I managed to create a reproducer. Here it is:</p>
  
  <p><strong>foobar.h</strong>:</p>
  
  <pre><code>#ifndef FOOBAR_H_
  #define FOOBAR_H_
  
  #include &lt;cmath&gt;
  
  #pragma omp declare simd
  inline double foo( double d ) {
      return sin( cos( exp( d ) ) );
  }
  
  double bar( double *v, int len );
  
  #endif
  </code></pre>
  
  <p><strong>foobar.cc</strong>:</p>
  
  <pre><code>#include "foobar.h"
  
  double bar( double *v, int len ) {
      double sum = 0;
      for ( int i = 0; i &lt; len; i++ ) {
          sum += foo( v[i] );
      }
      return sum;
  }
  </code></pre>
  
  <p><strong>simd.cc</strong>:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include "foobar.h"
  
  int main() {
  
      const int len = 100;
      double *v = new double[len];
  
      for ( int i = 0; i &lt; len; i++ ) {
          v[i] = i;
      }
  
      double sum = 0;
      #pragma omp simd reduction( +: sum )
      for ( int i = 0; i &lt; len; i++ ) {
          sum += foo( v[i] );
      }
  
      std::cout &lt;&lt; sum &lt;&lt; "  " &lt;&lt; bar( v, len ) &lt;&lt; std::endl;
  
      delete[] v;
  
      return 0;
  }
  </code></pre>
  
  <p><strong>compilation</strong>:</p>
  
  <pre><code>&gt; g++ -fopenmp -g simd.cc foobar.cc
  /tmp/ccI4e7ip.o: In function `_ZGVbN2v__Z3food':
  foobar.h:7: multiple definition of `_ZGVbN2v__Z3food'
  /tmp/cc4U8Qyu.o:foobar.h:7: first defined here
  /tmp/ccI4e7ip.o: In function `_ZGVbM2v__Z3food':
  foobar.h:7: multiple definition of `_ZGVbM2v__Z3food'
  /tmp/cc4U8Qyu.o:foobar.h:7: first defined here
  /tmp/ccI4e7ip.o: In function `_ZGVcN4v__Z3food':
  foobar.h:7: multiple definition of `_ZGVcN4v__Z3food'
  /tmp/cc4U8Qyu.o:foobar.h:7: first defined here
  /tmp/ccI4e7ip.o: In function `_ZGVcM4v__Z3food':
  foobar.h:7: multiple definition of `_ZGVcM4v__Z3food'
  foobar.h:7: first defined here
  /tmp/ccI4e7ip.o: In function `_ZGVdN4v__Z3food':
  foobar.h:7: multiple definition of `_ZGVdN4v__Z3food'
  foobar.h:7: first defined here
  /tmp/ccI4e7ip.o: In function `_ZGVdM4v__Z3food':
  foobar.h:7: multiple definition of `_ZGVdM4v__Z3food'
  foobar.h:7: first defined here
  collect2: error: ld returned 1 exit status
  &gt; c++filt _ZGVdM4v__Z3food
  _ZGVdM4v__Z3food
  &gt; c++filt _Z3food
  foo(double)
  </code></pre>
  
  <p>Gcc versions 4.9.2 and 5.1.0 both give the very same problem, while the Intel compiler version 15.0.3 compiles it just fine.</p>
  
  <hr>
  
  <p><strong>Final edit</strong>:<br>
  <a href="https://stackoverflow.com/questions/34091341/openmp-declare-simd-for-an-inline-function#comment55959437_34097496">Hristo Iliev's comment</a> and <a href="https://stackoverflow.com/q/34110703/5239503">Z boson's question</a> comfort me in the idea that my code is OpenMP compliant, and that this is a bug in GCC. I'll see to make further tests with the most up-to-date version I can find, and report it if needed.</p>