Reading Assembly

Part 5 · SIMD and the modern ISA

Why autovectorisation usually fails

The compiler wants to vectorise your loop. It is usually blocked, always for a nameable reason, and it will tell you which one if you ask.

30 mincontrasting casesPOE
What this lesson is trying to break (2)
  • The compiler vectorises anything simple.
  • If it did not vectorise, the compiler is not smart enough.

The compiler is trying. Vectorisation is enabled at -O2 in modern GCC and Clang and it will take it whenever it can prove the transformation legal. The interesting question is what stops it, and the answers are few and specific.

Ask, do not guess

Before anything else: the compiler will tell you.

-fopt-info-vec-missed          # GCC
-Rpass-missed=loop-vectorize   # Clang

Add either to Compiler Explorer’s flags and you get a line per loop explaining the refusal in English. This is the single most useful diagnostic in this area and it is almost unknown outside compiler circles. Everything below is context for interpreting what it says.

The four blockers

Varies: the single obstacle

BlockerExampleFixCost of the fix
Aliasingout[i] = in[i]*2 with two pointersrestrict, or Rust &mutNone — it is information, not a change
FP reductionfloat s; s += a[i];-ffast-math, or restructureDifferent results
Loop-carried dependencya[i] = a[i-1]+1Change the algorithmReal work; sometimes impossible
Unknown trip countwhile (*p) p++;Give it a lengthUsually an API change

Only the first has a free fix. The second changes your answers. The third and fourth need real changes. This is why 'just vectorise it' is not advice.

Aliasing is the common one and the only free win. Two pointer parameters might overlap, so processing four elements at once could differ from processing one at a time. The compiler emits a runtime check plus a scalar fallback (3.4), or gives up.

Floating-point reductions are refused for a correctness reason, not timidity. Vectorising a sum means four partial sums combined at the end — a different grouping — and FP addition is not associative, so the result can differ. The compiler will not silently change your numbers.

Predict firstcommit in writing, then look
int  sum_i(const int   *a, int n) { int   s=0; for(int i=0;i<n;i++) s+=a[i]; return s; }
float sum_f(const float *a, int n) { float s=0; for(int i=0;i<n;i++) s+=a[i]; return s; }

Identical structure. One element type differs.

Where Rust has a structural advantage

The aliasing blocker is where the borrow checker pays off in generated code.

In C, telling the compiler two pointers do not overlap means writing restrict, and nothing checks that you are right. Lying is undefined behaviour with no diagnostic.

In Rust, &mut T is exclusivity, enforced at compile time. rustc emits LLVM’s noalias on those references, so the compiler gets the information for free and it cannot be wrong.

So the practical situation is: Rust often vectorises where equivalent C needs a manual annotation. This is a genuine, measurable benefit of the ownership model that has nothing to do with memory safety, and it is a good thing to be able to point at when someone asks what the borrow checker is for.

Explain it to yourselfwrite it — thinking it does not count

You have a hot loop over f64 that will not vectorise. Your team wants -ffast-math added globally to the build.

Write your response. Cover: what it would actually permit beyond reassociation, what you would want to know about the code first, and a narrower alternative.

What you should now be able to say

  • The compiler wants to vectorise and is blocked for nameable reasons.
  • Ask it with -fopt-info-vec-missed or -Rpass-missed=loop-vectorize.
  • Four blockers: aliasing, FP reduction, loop-carried dependency, unknown trip count.
  • Only aliasing has a free fix; -ffast-math changes your results and permits more than reassociation.
  • Integer reductions vectorise and float ones do not — semantics, not compiler quality.
  • Rust’s &mut gives noalias for free, so it vectorises where C needs restrict.

Next: 5.3 — Reading vectorised output.

In the wildgo read the real thing now, while it is fresh
  • GCC vectorisation diagnosticsAdd -fopt-info-vec-missed to any Compiler Explorer session. GCC will explain in English why each loop was not vectorised. Clang uses -Rpass-missed=loop-vectorize. Use it before speculating.
Scheduled for recall3 items added to your review queue

These are not shown to you now on purpose. They will surface in Review tomorrow, mixed in among items from other parts of the course — not grouped by topic. Sorting out which idea applies is the part that transfers.