title: Intel C Compiler giving the wrong output when using openmp
body: <p>I am trying to use the Intel C compiler for the first time and am getting completely the wrong answers.  What am I doing wrong?</p>
  
  <p>I have some code as follows:</p>
  
  <pre><code>#include &lt;stdint.h&gt;
  #include &lt;stdio.h&gt;
  
  #define CHUNK_SIZE 12
  #define NUM_THREADS 8
  
  #define popcnt __builtin_popcountll
  #define BILLION (1000 * 1000 * 1000)
  #define UPDATE_ROW_PPROD() \
      update_row_pprod(row_pprod, row, rows, row_sums, mask, mask_popcnt)
  
  typedef __int128 int128_t;
  
  static inline int64_t update_row_pprod
  (
      int64_t* row_pprod, int64_t row, int64_t* rows,
      int64_t* row_sums, int64_t mask, int64_t mask_popcnt
  )
  {
      int64_t temp = 2 * popcnt(rows[row] &amp; mask) - mask_popcnt;
  
      row_pprod[0] *= temp;
      temp -= 1;
      row_pprod[1] *= temp;
      temp -= row_sums[row];
      row_pprod[2] *= temp;
      temp += 1;
      row_pprod[3] *= temp;
  
      return row + 1;
  }
  
  int main(int argc, char* argv[])
  {
      int64_t size = argc - 1, rows[argc - 1];
      int64_t row_sums[argc - 1];
      int128_t permanent = 0, sign = size &amp; 1 ? -1 : 1;
  
      if (argc == 2)
      {
          printf("%d\n", argv[1][0] == '-' ? -1 : 1);
          return 0;
      }
  
      for (int64_t row = 0; row &lt; size; row++)
      {
          char positive = argv[row + 1][0] == '+' ? '-' : '+';
  
          sign *= ',' - positive;
          rows[row] = row_sums[row] = 0;
  
          for (char* p = &amp;argv[row + 1][1]; *p; p++)
          {
              rows[row] &lt;&lt;= 1;
              rows[row] |= *p == positive;
              row_sums[row] += *p == positive;
          }
  
          row_sums[row] = 2 * row_sums[row] - size;
      }
  
      #pragma omp parallel for reduction(+:permanent) num_threads(NUM_THREADS)
      for (int64_t mask = 1; mask &lt; 1LL &lt;&lt; (size - 1); mask += 2)
      {
          int64_t mask_popcnt = popcnt(mask);
          int64_t row = 0;
          int128_t row_prod = 1 - 2 * (mask_popcnt &amp; 1);
          int128_t row_prod_high = -row_prod;
          int128_t row_prod_inv = row_prod;
          int128_t row_prod_inv_high = -row_prod;
  
          for (int64_t chunk = 0; chunk &lt; size / CHUNK_SIZE; chunk++)
          {
              int64_t row_pprod[4] = {1, 1, 1, 1};
  
              for (int64_t i = 0; i &lt; CHUNK_SIZE; i++)
                  row = UPDATE_ROW_PPROD();
  
              row_prod *= row_pprod[0], row_prod_high *= row_pprod[1];
              row_prod_inv *= row_pprod[3], row_prod_inv_high *= row_pprod[2];
          }
  
          int64_t row_pprod[4] = {1, 1, 1, 1};
  
          while (row &lt; size)
              row = UPDATE_ROW_PPROD();
  
          row_prod *= row_pprod[0], row_prod_high *= row_pprod[1];
          row_prod_inv *= row_pprod[3], row_prod_inv_high *= row_pprod[2];
          permanent += row_prod + row_prod_high + row_prod_inv + row_prod_inv_high;
      }
  
      permanent *= sign;
  
      if (permanent &lt; 0)
          printf("-"), permanent *= -1;
  
      int32_t output[5], print = 0;
  
      output[0] = permanent % BILLION, permanent /= BILLION;
      output[1] = permanent % BILLION, permanent /= BILLION;
      output[2] = permanent % BILLION, permanent /= BILLION;
      output[3] = permanent % BILLION, permanent /= BILLION;
      output[4] = permanent % BILLION;
  
      if (output[4])
          printf("%u", output[4]), print = 1;
      if (print)
          printf("%09u", output[3]);
      else if (output[3])
          printf("%u", output[3]), print = 1;
      if (print)
          printf("%09u", output[2]);
      else if (output[2])
          printf("%u", output[2]), print = 1;
      if (print)
          printf("%09u", output[1]);
      else if (output[1])
          printf("%u", output[1]), print = 1;
      if (print)
          printf("%09u\n", output[0]);
      else
          printf("%u\n", output[0]);
  }
  </code></pre>
  
  <p>If I compile it with</p>
  
  <pre><code>gcc -Wall -std=c99 -fopenmp  -o permanent permanent.c
  </code></pre>
  
  <p>I can then run it with </p>
  
  <pre><code>permanent -+ -+
  </code></pre>
  
  <p>and get the output</p>
  
  <pre><code>-2
  </code></pre>
  
  <p>which is correct.</p>
  
  <p>If I instead compile using the Intel C compiler (17.0.1) with</p>
  
  <pre><code>icc -std=c99 -qopenmp -Wall permanent.c
  </code></pre>
  
  <p>and then do</p>
  
  <pre><code>a.out -+ -+
  </code></pre>
  
  <p>I get</p>
  
  <pre><code>11910984139051480114196905982
  </code></pre>
  
  <hr>
  
  <p>As noted in the comments, if you remove the -qopenmp then icc produces a version that runs correctly, albeit only on one core. </p>