I’ve tried two things, both don’t work, for different reasons:

$ mlir-opt-16 linalg.mlir -opaque-pointers=0 --one-shot-bufferize
linalg.mlir:4:13: error: 'tensor.empty' op cannot be bufferized, but can be converted to bufferization.alloc_tensor
%kernel = tensor.empty() : tensor<3x3xf32>
^
linalg.mlir:4:13: note: see current operation: %0 = "tensor.empty"() : () -> tensor<3x3xf32>
linalg.mlir:4:13: error: failed to bufferize op
%kernel = tensor.empty() : tensor<3x3xf32>
^
linalg.mlir:4:13: note: see current operation: %0 = "tensor.empty"() : () -> tensor<3x3xf32>

But ultimately I guess the --empty-tensor-to-alloc-tensor is also not right. My understanding is that the empty tensor is just to specify the shape, is that right? Should I change the input somehow? There’s frustratingly little documentation on the linalg named ops… It seems that in the second version there’s some dce going on that removes the whole linalg operation, is there a way to prevent that?

I have a constraint which is that I link the resulting function with c code that expects it to have the same signature as void foo(const double* x, double* y). I’m not able to get the expected bufferization of destination-passing style.

linalg.mlir -opaque-pointers=0 --one-shot-bufferize here you get the error tensor.empty cannot be bufferized. This is correct since tensor.empty should not bufferize. As you said, tensor.empty just defines the shape of a tensor. If you want to force an allocation, you should use empty-tensor-to-alloc-tensor.

linalg.mlir -opaque-pointers=0 --empty-tensor-to-alloc-tensor --one-shot-bufferize is the right way. I would add one option to one-shot: --one-shot-bufferize="bufferize-function-boundaries". The reason why DCE removes the convolution operation is that, from a tensor perspective, %res is dead; try to return it from the function, and now you should see what you expect. Remember that output tensors in Linalg are of two flavors: init-tensor or shape-only. The former provides an initial value, while the latter is just a shape and should not be used in the payload of the linalg op. I hope this allows you to make progress!

@chelini, thank you for your reply. It appears that I have misunderstood the way that the kernel is used. None of the definitions of max pooling I’ve come across have a similar parameter. I’m confused what values it should be filled with to result in the same semantics as the PyTorch definition, which only takes a shape as a parameter. Is there any documentation anywhere as to the definition of the linalg op? I have not found any.

Ok, there isn’t some definition I’m not aware of, K is not used in that definition, only its shape. It seems that my intuition was correct, the tensor operand is just a way to specify the shape, and the contents are ignored. I’ll try to get the bufferization to work with @Groverkss’s help.