This is an archive of the discontinued LLVM Phabricator instance.

[mlir][Bufferization] Extend the folding of to_tensor(to_memref)
AbandonedPublic

Authored by mamrami on Jan 20 2023, 2:18 AM.

Details

Summary

The folding was allowed only if to_tensor appeared right after to_memref.
This change allows the folding as long as there are no interleaved users
of the result memref.

Diff Detail

Event Timeline

mamrami created this revision.Jan 20 2023, 2:18 AM
mamrami requested review of this revision.Jan 20 2023, 2:18 AM
mamrami updated this revision to Diff 490760.Jan 20 2023, 2:27 AM

Change operation in lit test.

mamrami updated this revision to Diff 490762.Jan 20 2023, 2:32 AM

lit test change

springerm requested changes to this revision.Jan 20 2023, 2:52 AM

This would fold in cases such as this one right? That's not safe.

%alias = memref.subview %arg0
%0 = bufferization.to_memref %arg0 : memref<?xf32>
%1 = "use"(%alias) : (memref<?xf32>) -> memref<?xf32>
%2 = bufferization.to_tensor %0 : memref<?xf32>

My suggestion would be to remove to_tensor and to_memref entirely and using unrealized_conversion_cast instead. We can discuss on Discourse.

This revision now requires changes to proceed.Jan 20 2023, 2:52 AM

This would fold in cases such as this one right? That's not safe.

%alias = memref.subview %arg0
%0 = bufferization.to_memref %arg0 : memref<?xf32>
%1 = "use"(%alias) : (memref<?xf32>) -> memref<?xf32>
%2 = bufferization.to_tensor %0 : memref<?xf32>

Isn't this covered by the isBeforeInBlock condition?

mehdi_amini added inline comments.Jan 20 2023, 3:16 AM
mlir/test/Dialect/Bufferization/canonicalize.mlir
48

We should also have the positive test case for the ordering:

  %0 = bufferization.to_memref %arg0 : memref<?xf32>
  %2 = bufferization.to_tensor %0 : memref<?xf32>
  %1 = "use"(%0) : (memref<?xf32>) -> memref<?xf32>
  return %2 : tensor<?xf32>
}

This should fold right?

springerm accepted this revision.Jan 20 2023, 3:23 AM

This would fold in cases such as this one right? That's not safe.

%alias = memref.subview %arg0
%0 = bufferization.to_memref %arg0 : memref<?xf32>
%1 = "use"(%alias) : (memref<?xf32>) -> memref<?xf32>
%2 = bufferization.to_tensor %0 : memref<?xf32>

Isn't this covered by the isBeforeInBlock condition?

Ahh yes, the IR that I wrote is not even valid. The case that I was thinking of cannot happen. (Was thinking of to_memref(to_tensor) folding....)

This revision is now accepted and ready to land.Jan 20 2023, 3:23 AM
nicolasvasilache requested changes to this revision.Jan 20 2023, 3:24 AM

to_tensor and to_memref are fundamentally broken abstractions with tricky constraints specified in doc text that only amount to wishful thinking.
They are part of the difficulties I had with using bufferization in a sane way a while back (https://discourse.llvm.org/t/properly-using-bufferization-related-passes/2913) until I decided things were too broken and started a new bufferization effort (https://discourse.llvm.org/t/rfc-linalg-on-tensors-update-and-comprehensive-bufferization-rfc/3373).

They have survived until now for purposes of "compatibility" with some downstream uses and "composability".
I believe it is time to cut the cord.

mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
569

you need to consider all possible aliases of the memref, this requires a much more serious analysis

This revision now requires changes to proceed.Jan 20 2023, 3:24 AM
springerm added a comment.EditedJan 20 2023, 3:33 AM

I believe it is time to cut the cord.

It would indeed be better to remove them entirely (as a cleanup), as we no longer have a need for them. We moved to a bufferization that bufferizes to entire IR in one go. @mamrami Can you describe your use case in Discourse, so we can discuss alternatives?

@springerm - my case is a bit different/special. I have an IR with functions that have memref based signature.
Some of them have implementation - and it is a tensor based implementation, meaning I have to_tensor/to_memrefs on args/results.
I had to inline some of them to one function that will be pure tensor based function. On this function I run OneShotBufferize.
After inlining I had the intermediate to_tensor(to_memref), and I expected them to fold.
That's how I got to all the wondering about the folding.
I understand now that the general case is much more complicated than my case.
So I decided to manually move the to_tensor right after their to_memref - because in my case I know it is not changing the meaning of the IR.

my case is a bit different/special. I have an IR with functions that have memref based signature.
Some of them have implementation - and it is a tensor based implementation, meaning I have to_tensor/to_memrefs on args/results.

Is it possible to give them a tensor signature? Then you could bufferize the entire thing with One-Shot Bufferize.

mamrami abandoned this revision.Jan 26 2023, 4:48 AM

Is it possible to give them a tensor signature? Then you could bufferize the entire thing with One-Shot Bufferize.

It will require redesigning our whole flow 😐