Phase 2, week 12retrospective

Layout propagation

Layout propagation avoids the transpose copy, not its cost: an innermost iterator that blocks unit stride turns loads into vlse32.


Layout lives in the map

A matmul needs B indexed by (k, n). If B is stored N-major, you can transpose the buffer, which is a full copy, or write the map that matches the storage, which is address arithmetic. Named ops take an explicit indexing_maps attribute, and the linalg docs show the transpose form on linalg.batch_matmul; the 2-D case is the same attribute on linalg.matmul:

linalg.matmul indexing_maps = [affine_map<(m, n, k) -> (m, k)>,
                               affine_map<(m, n, k) -> (n, k)>,
                               affine_map<(m, n, k) -> (m, n)>]
    ins(%a, %b_t : memref<64x64xf32>, memref<64x64xf32>)
    outs(%c : memref<64x64xf32>)

The map says what the access pattern is; the buffer layout stays the caller’s problem. That is the whole point of separating iteration space from storage.

Loop order is part of the same decision

iterator_types fixes the loop order after -convert-linalg-to-loops, and the innermost iterator decides which operand is unit-stride. The epilogue adds a constraint: the bias is contiguous along n, so n has to be innermost for the bias load to be a plain vector load like the store. Choose the order that makes both the B access and the bias access contiguous in the same dimension, and the matmul’s map and the epilogue’s map agree with no transpose anywhere.

Things that break

The maps are right and the loop order is not, so the vectorizer emits vlse32.v strided loads, or scalarizes, and the load count is a multiple of what a unit-stride access would need. The disassembly is the evidence and a load count is the number. The second failure is a pass inserting linalg.transpose or linalg.copy to satisfy a layout assumption: after bufferization it is an allocation plus a copy loop, and the transpose you removed from the map came back as a pass. Grep for both op names before you claim the layout is free.

Sources

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

B is stored N-major and the matmul needs it indexed by K. What is the cheapest legal expression?

Which iterator order keeps the bias epilogue contiguous?

The maps are right and the disassembly is full of `vlse32.v`. What went wrong?

0 / 3 correct

← back to the map