Hacker News new | ask | show | jobs
by trealira 941 days ago
The main issue is that C doesn't have a way to pass arrays of any size to functions while preserving their type (the size is part of an array's type in C); by convention, one generally passes a pointer to its first element and a separate length parameter. A compiler cannot know that any two pointers do not point to the same location. Hence, it's harder to vectorize code like this, because each store to result[i] may affect arr1[i] or arr2[i]; in other words, the pointers might alias. In C89:

  /* They're all the same length */
  void add(float *result, float *arr1, float *arr2, size_t len)
  {
      size_t i;

      for (i = 0; i < len; ++i)
          result[i] = arr1[i] + arr2[i];
  }
The solution is supposed to be the "restrict" keyword, which informs the compiler that other pointers do not alias this one. It was added in C99. You declare a pointer that doesn't alias like this:

  float *restrict float_ptr;
If a restrict pointer is aliased by another pointer, the behavior is undefined.

https://en.wikipedia.org/wiki/Restrict

It's hard to judge the extent to which this helps. Apparently, when Rust annotated all its mutable references and Box<T> types with the LLVM equivalent of the "restrict" annotation, they exposed a lot of bugs in LLVM's implementation of it, because most C code doesn't use "restrict" pointers as extensively as Rust code uses mutable references and Boxes.