core22 min studyLesson 109 in Engineering

SIMD: lanes have exact arithmetic semantics

Trace SSE2 packed integer addition, distinguish wrapping from saturation, and count vector tails honestly.

On this page

What you’ll understand

  • Compute independent fixed-width packed lane results.
  • Distinguish ordinary packed addition, saturating addition, and reduction.
  • Calculate vector instruction counts and tail work under explicit assumptions.

Single-instruction multiple-data operations apply specified work to several lanes packed into a register. That can increase arithmetic throughput, but lane width and operation semantics still determine correctness. This lesson uses the SSE2 XMM form of PADDD: four independent 32-bit integer additions in a 128-bit register. It does not assume every vector instruction has the same lane shape, flag behavior, alignment requirement, or performance.

A lane is a bounded integer operation

For PADDD, corresponding 32-bit lanes are added and each result keeps its low 32 bits. A carry from one lane does not flow into the next lane, and this packed integer addition does not report its lane overflows through ordinary arithmetic flags. Thus a vector is not automatically one giant 128-bit integer. Signed and unsigned interpretations share these wrapping result bits, while application-level meaning still depends on which interpretation and range the program requires.

Saturating instructions implement a different operation: a result outside the selected signed or unsigned range is clamped to an endpoint. They are useful for certain bounded pixel or signal formats but are not interchangeable with modular integer arithmetic. Nor does packed addition compute a horizontal reduction across lanes; each lane remains separate until an instruction explicitly combines or rearranges values. Read the actual instruction and operand form rather than inferring semantics from a vector type in source code.

cj=(aj+bj) mod 232,j∈{0,1,2,3}c_j=(a_j+b_j)\bmod2^{32},\qquad j\in\{0,1,2,3\}
This is SSE2 PADDD for a 128-bit XMM operand, with four dimensionless 32-bit lane values. Carries are discarded within each lane and do not propagate between lanes.↔ Scroll wide equations horizontally.

Vectorize the data path, including its edges

A loop over n elements may process groups of four with this lane shape, leaving up to three tail elements. The tail still needs correct handling, such as a scalar cleanup or an appropriate supported masked operation in another ISA extension. Reading past the object boundary is not justified by discarding unwanted lane results later. Alignment requirements also belong to specific load and store instructions; some forms support unaligned data, while others impose constraints. A general claim that all vector loads require identical alignment is wrong.

Wider arithmetic can expose memory traffic as the limiting cost. Loads, stores, shuffles, dependency chains, and the availability of functional units all matter. Four lanes do not promise fourfold end-to-end speedup. When vectorizing a reduction over floating-point values, reassociation can also alter rounding because floating-point addition is not associative. A compiler’s legal transformations depend on language and compilation options. First preserve the intended numeric contract, then compare vector and scalar implementations on representative data.

q=⌊nL⌋,r=n−Lq,0≤r<Lq=\left\lfloor\frac{n}{L}\right\rfloor,\qquad r=n-Lq,\qquad 0\leq r<L
n counts elements, L is lanes per vector operation, q counts full groups, and r counts remaining elements. This is a grouping identity, not an instruction-throughput guarantee; setup and memory operations are excluded.↔ Scroll wide equations horizontally.

Inspect semantics before reporting speedup

Write a short lane table with normal values and boundary values. Compute each expected result independently, including wraparound or saturation, and compare the output lane order after any packing or shuffle. Then inspect generated code to confirm the expected instruction set was actually selected. A generic binary may use a fallback path; enabling an unsupported extension can make a binary unusable on another host. Feature detection and operating-system support are part of deploying code that relies on wider register state.

The vector lab shows one two-dimensional vector and its x and y projections as angle and magnitude change. This mathematical vector is different from a SIMD register containing several machine lanes. Predict the projections and observe how they change continuously, then explain why no carries, wrapping lanes, or packed instruction effects are displayed. The comparison is deliberate: the shared word vector does not grant the lab the semantics of a particular instruction or prove that component arithmetic executes in parallel.

Four lanes, four separate wraparound decisions

Use SSE2 PADDD on lanes a=[0xFFFFFFFF,10,0x7FFFFFFF,100] and b=[1,20,1,200], listing lanes in the same logical order.

  1. Lane zero sums to 4,294,967,296, exactly 2^32, so its stored low 32 bits are zero. The discarded carry does not increment lane one.

  2. Lane one becomes 10+20=30. Lane two becomes 2,147,483,648, whose bit pattern represents minus 2,147,483,648 if interpreted as a signed 32-bit integer. The packed operation still stores those bits.

  3. Lane three becomes 100+200=300. The final lane list is [0,30,2147483648,300] when read unsigned. No ordinary carry or overflow flag summarizes these individual lane range events.

The result

Each lane wraps independently. A saturating operation or a horizontal sum would produce a different result and require different instructions.

Explore the model

Interactive lab

Interactive lab · vectors

Mathematical components are not machine lanes

Change angle and magnitude for one 2D vector and predict its x and y projections. This continuous geometry model does not display SIMD packing, integer wraparound, flags, or processor execution.

Mathematical components are not machine lanesPlayback traces a fixed vector and its projections. Angle and magnitude set the geometry; the moving marker does not change them. Current readings: x component: 1.393; y component: 0.975; Magnitude: 1.7. All parameters are adjustable with the labeled controls below.−7.46−3.7303.737.46−3.5−1.7501.753.5xyvvₓ = 1.39
Vectorx / y projectionsTrace marker
x component
1.393
y component
0.975
Magnitude
1.7
t = 0 s

Playback traces a fixed vector and its projections. Angle and magnitude set the geometry; the moving marker does not change them. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forA mathematical vector and a SIMD register need separate definitions despite their shared name.

Check your understanding

What does SSE2 PADDD do when one 32-bit lane adds 0xFFFFFFFF and 1?

Try it yourself

A 19-element array is processed four elements per packed group, with a scalar tail and no overread. How many full groups and tail elements are required? Does that imply fourfold speedup?

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

Divide the element count into complete groups and a remainder.

Compare with the solution

There are floor(19/4)=4 full groups covering 16 elements, then three scalar tail elements. Grouping reduces some arithmetic instruction counts, but load/store cost, setup, tail handling, and resource limits prevent inferring a fourfold speedup from lane count alone.

Take it with you

  • Packed lanes obey the exact width and operation semantics of their instruction.
  • Wrapping, saturation, and reduction are different computations.
  • Vector width alone does not determine whole-program acceleration.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.