Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Consider the simple loop

  void f(int *a, const int *b, unsigned size) {
    for (unsigned i = 0; i < size; ++i) {
      a[i] = b[i] * 2;
    }
  }
This is the LLVM IR generated by `clang -Ofast -c -o - -emit-llvm -S`:

https://gist.github.com/zwarich/21cf3a0b2387302ea48b

Notice the `vector.memcheck` block, which is doing a dynamic aliasing check to decide whether to use the vectorized code. If I add `restrict`, e.g.

  void f(int *restrict a, const int *b, unsigned size) {
    for (unsigned i = 0; i < size; ++i) {
      a[i] = b[i] * 2;
    }
  }
then that dynamic check goes away:

https://gist.github.com/zwarich/48fd374becf5f891cb5a

However, if I put the vectorized loop in a function that gets inlined, e.g.

  static void f(int *restrict a, const int *b, unsigned size) {
    for (unsigned i = 0; i < size; ++i) {
      a[i] = b[i] * 2;
    }
  }

  void g(int *a, int *b, unsigned size) {
    f(a, b, size);
  }
the dynamic aliasing check reappears:

https://gist.github.com/zwarich/3e75f17de835dd9064ee

This is because LLVM's loop vectorizer runs after inlining and the standard optimization passes (which are run in a bottom-up traversal of the SCCs of the callgraph, interleaved with inlining). The `noalias` attribute on function parameters, which is what represents `restrict` in LLVM IR, disappears upon inlining. Many other compilers do something similar, although some like IBM's XLC can preserve `restrict` upon inlining.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: