Dynamic vectorization
Dynamic vectorization uses strip-mining and masks; vsetvli supplies the runtime vector length but not the bounds.
Strip-mine, then mask
Dynamic vectorization keeps the vector shape static and makes the trip count dynamic. The loop walks the array in vector-sized steps, and the final step is short:
%mask = vector.create_mask %bound : vector<[4]xi1>
%v = vector.transfer_read %A[%i], %pad, %mask
{in_bounds = [false]} : memref<?xf32>, vector<[4]xf32>
The mask is how the source says which lanes are real. On RISC-V it can lower to a masked load, or to a length-bounded load where vl carries the count. Both are correct only if the mask and the length describe the same edge.
The length is an operand
vsetvli does not know the array bound. It computes vl = min(avl, VLMAX), where AVL is a value you put in a register:
sub a0, s1, s0 # avl = n - i
vsetvli t0, a0, e32, m1, ta, ma
vle32.v v8, (a1)
The bound lives in a0, computed by ordinary scalar code. VLMAX comes from LMUL, VLEN and SEW; vl is the smaller of that and the remaining count. A loop that advances by VLMAX instead of the returned vl is wrong at the edge, and the error is a wrong result rather than a fault. This is the same subtraction a scalar loop performs, now feeding the vector configuration instead of a branch.
Check the mask op and the transfer syntax on your pinned release; vector.mask and the predicate form have moved more than once. vector.create_mask takes index operands.
Things that break
Using VLMAX as the step overruns the buffer when the available length was smaller. A mask computed from the tile index rather than the element count leaves the last lanes live. And a short final iteration under ta leaves the tail lanes unspecified, so an accumulator that survives the loop needs tu or an explicit merge. Confirm which policy your build emits before trusting a tail sum.
Sources
- MLIR vector dialectdocs · LLVM 19
- LLVM RISC-V Vector Extension guidedocs · LLVM 19
- RISC-V Vector Extension specification releasesdocs · v1.0
A version records the documentation the claim was checked against, not a house pin. Confirm flags with --help on the release you installed.
Check yourself
What does `vsetvli` know about the array bound?
Why keep both a mask and a runtime vector length at the edge?
What should a strip-mined loop add to the pointer each iteration?