Phase 1, week 5retrospective

One-shot bufferization

One-shot bufferization copies only where aliasing or a non-writable buffer requires it, not for every tensor value.


Crossing the line

One-shot bufferization rewrites tensor SSA values into memrefs. It runs as a single pass over a function, and function boundaries need to be opted in:

mlir-opt tiled.mlir --one-shot-bufferize='bufferize-function-boundaries'

With that option, a tensor argument becomes a memref argument and a tensor result becomes a memref result, so the caller’s buffer is the one the callee writes. Inside the body, a tensor.extract_slice of a tile becomes a memref.subview, a linalg.matmul reads and writes those subviews, and the tensor.insert_slice that wrote a tile back usually disappears because the tile was already in the destination.

The pass is monolithic in the useful sense: one analysis over the whole function, then one rewrite. It does not interleave decisions with rewrites, so the copy count is a property of the analysis, not of pass ordering.

Copies are a diagnosis

The analysis is greedy and prefers in-place. A copy appears in two situations: overwriting the buffer would destroy data that is still read later, or the buffer is not writable at all. To see which, ask the pass to stop before rewriting:

mlir-opt tiled.mlir \
  --one-shot-bufferize='bufferize-function-boundaries test-analysis-only print-conflicts'

Every tensor operand then carries an in-place flag, and each conflict is tagged with the definition, the conflicting write and the read that forced the copy. Read that before reading the generated memref.copy.

Things that break

An unexpected memref.alloc means the value had no destination: it came from tensor.empty or tensor.generate, and a fresh buffer was the only option. Fix that in tensor land by giving the consumer an outs operand. An op without BufferizableOpInterface makes the pass fail outright, and allow-unknown-ops swaps that failure for boundary ops that keep the tensor alive. Also expect allocations with no deallocation: one-shot bufferization never deallocates, and deallocation is a separate pass.

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

When does one-shot bufferization insert a copy?

What does `test-analysis-only print-conflicts` give you?

You see a `memref.alloc` you did not expect. What does it most likely mean?

0 / 3 correct

← back to the map