<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div>Hi -- I have found a bug in an HPC code where llvm is vectorizing a loop on Skylake that has an obvious recurrence. I derived a small test case based on the original benchmark below:</div><div><br></div><div>/*****************************************************************/</div><div><div>static void  __attribute__ ((always_inline)) one(</div><div>  const int *restrict in, const int *const end,</div><div>  const unsigned shift, int *const restrict index,</div><div>  int *const restrict out)</div><div>{</div><div>  do {</div><div>    int a_idx = *in>>shift;</div><div>    int b_idx = index[a_idx];   </div><div>    out[b_idx] = *in;                // <-- reccurence as index[a_idx] can be the</div><div>    index[a_idx]++;                 //      same and incremented within the vector</div><div>  } while(++in!=end);              //     which leads to incorrect results</div><div>}</div><div><br></div><div>#ifndef NO_TWO</div><div>static void  __attribute__ ((noinline)) two(</div><div>  const int *restrict in, const int *const end,</div><div>  const unsigned shift, int *const restrict index,</div><div>  int *const restrict out)</div><div>{</div><div>  do out[index[(*in>>shift)]++]=*in; while(++in!=end);</div><div>}</div><div>#endif</div><div><br></div><div>void parent(</div><div>  int digits, int n, int *restrict work, int * restrict idx,</div><div>  int *restrict shift, int **restrict indicies)</div><div>{</div><div>  int *in = work;</div><div>  int *dst = work+n;</div><div>//  int *indicies[1024];</div><div>//  int shift[1024];</div><div>  int d;</div><div>  for(d=1;d!=digits-1;++d) {</div><div>    int *t;</div><div>    one(in,in+n,shift[d],indicies[d],dst);</div><div>    t=in,in=dst,dst=t;</div><div>  }</div><div>#ifndef NO_TWO</div><div>  two(in,in+n,shift[d],indicies[d],idx);</div><div>#endif</div><div>}</div></div><div>/*****************************************************************/<br></div><div><div><div><br class="gmail-Apple-interchange-newline">clang -S -O2 -Rpass=loop-vectorize small.c  -march=skylake-avx512</div><div>small.c:6:3: remark: vectorized loop (vectorization width: 16, interleaved count: 1) [-Rpass=loop-vectorize]</div><div>  do {</div><div>  ^</div></div></div><div><br></div><div>I believe the problem to be a issue with dependency information getting destroyed because if you remove the two() function (or compile one() on its own, or prevent inlining of one()), it correctly prevents vectorization. <br></div><div><br></div><div><div>clang -S -O2 -Rpass=loop-vectorize -Rpass-missed=loop-vectorize small.c  -march=skylake-avx512 -DNO_TWO</div><div>small.c:6:3: remark: loop not vectorized [-Rpass-missed=loop-vectorize]</div><div>  do {</div></div><div><br></div><div>I did trace it down to possibly being something within DepChecker->areDepsSafe() as it returns true for the incorrect case.</div><div><br></div><div>Thanks,</div><div><br></div><div>Scott</div></div></div></div></div></div></div></div>