4 ms·
The compiler could generate both vectorized and non-vectorized variants and decide dynamically which one to use based on a simple aliasing check. That's an appr
by tom_mellior 7y ago
The compiler could generate both vectorized and non-vectorized variants and decide dynamically which one to use based on a simple aliasing check. That's an approach that would be more usual for JIT compilers than AOT compilers, but habits can change.
- gpderetta 7y agoThat's true. In fact GCC should be able to do that in principle. I guess it only does it if it believes that the vectorization is significantly profitable. edit: it is possible it only does it on PGO builds.
- BeeOnRope 7y agoI linked an example [1] in a parallel reply that shows gcc (and clang) doing it at -O3 without PGO, for the case of possibly overlapping arrays. --- [1] https://godbolt.org/z/9vZfl_ https://godbolt.org/z/9vZfl_
- BeeOnRope 7y agoYeah I came here to say this: I don't see a good way to prove this at compile time, but you could always do a dynamic check. In general, compilers don't generate runtime checks like this. In the case of aliasing problems, however, they actually do make such checks, but usually only in the case of possibly overlapping arrays. An example: https://godbolt.org/z/9vZfl_ https://godbolt.org/z/9vZfl_ Both gcc and clang make a check to see if the x and y arrays overlap, and if they do they fall back to a scalar loop (instructions ending in ss: scalar single-precision) - but if there is no overlap they proceed with the vectorized approach (instructions ending in ps: packed single-precision). So I guess these cases were important enough that they got specific handling in the compiler, but I haven't seen it for possible aliasing with a scalar, even though the same type of check could be used. Actually it's a bit trickier, because the compiler wants to know the array size to make this calculation, but the array size itself, which comes from size() is the thing subject to aliasing! So it takes a more complex analysis to show that it's safe.
- gpderetta 7y agoIf I'm reading the generated asm correctly (which I might well be not), the following function is vectorized conditional to a runtime alias check (the non vectorized case is completely removed if the pragma is uncommented). So even scalars seem to be handled: void inc(float* x, float* c, size_t n) { //#pragma GCC ivdep for (int i = 0; i < n; ++i) x[i]+= *c; } the issue really seems to be that the compiler just gives up very early if the iteration count is not a loop invariant.
- BeeOnRope 7y agoYeah, I read it the same as you: so alias checks can definitely happen even for single values. It seems like it's not just the loop counts that's the problem: in the blog post even when size is a local, it fails to check to see if the vector array pointer itself can alias. I.e., analogous to incB here: https://godbolt.org/z/ptQZcs https://godbolt.org/z/ptQZcs incA is like your example: the possibly aliasing is between the array and the value added, and an alias check occurs. incB is like the v[i] example: possible aliasing is between the array and the pointer to the same array, no check and conservative code is generated. Interesting...