Auto-vectorization is invisible until you look at compiler output or generated assembly. This optional lesson connects Lesson 9.8 to the measurement workflow from Lesson 0.4.
Reading GCC vectorization reports
GCC can print vectorization decisions when you pass optimization and info flags:
Look for lines such as vectorized or not vectorized with a reason (data dependency, unknown trip count, function call inside the loop). Clang offers similar diagnostics with -Rpass=loop-vectorize and related flags.
Compiler Explorer workflow
Paste the same loop into Compiler Explorer with -O3 -std=c++23 and inspect the assembly pane. A vectorized loop on x86_64 often shows packed instructions (addps, vmovups, vpaddd) instead of one scalar add per element. If you only see scalar add in a tight numeric loop, the compiler kept the loop scalar, check the report for the reason before rewriting by hand.
A minimal intrinsic example (SSE2)
Intrinsics name vector registers and instructions explicitly. The example below uses SSE2 (__m128), available on essentially all x86_64 targets. AVX2 (__m256) follows the same pattern but typically requires -mavx2 at compile time.
Prefer intrinsics only after profiling shows a hot loop and the compiler will not vectorize it safely. Maintain a scalar fallback path or gate AVX code behind CPU feature detection on shipped binaries.
When not to hand-write SIMD
If the compiler already vectorizes the loop, intrinsics usually add portability cost without benefit. If the loop has gathers, branches, or irregular memory access, SIMD may not apply at all. Measure before and after, and keep the scalar version in tests for correctness.