SIMD & Vectorization
One instruction, many elements. What makes a loop vectorizable, what stops the compiler from doing it, and where data-level parallelism sits among the other kinds.
Instruction-level, data-level, thread-level and core-level parallelism are four different mechanisms with four different requirements, four different costs and four different failure modes. Most confused performance arguments come from conflating two of them.
A vector register holds several values and a vector instruction applies one operation to all of them at once. It is the cheapest parallelism on the machine — single-threaded, race-free, and frequently left unused because a single unprovable pointer relationship disabled it.
The transformation from one-element-per-iteration to many, and the four conditions that have to hold for it to be legal. Most loops that fail to vectorise fail on a single unprovable assumption rather than on anything fundamental.
Compilers vectorise loops automatically, sometimes. It is a best-effort optimisation with no guarantee, it fails silently, and it can stop working after an unrelated edit — so the only responsible position is to check rather than believe.