This is an archive of the discontinued LLVM Phabricator instance.

[mlir] Simplify and better document std.view semantics
ClosedPublic

Authored by nicolasvasilache on May 6 2020, 7:18 PM.

Details

Summary

This discussion raised some concerns with ViewOp.

In particular, the handling of offsets is incorrect and does not match the op description.
Note that with an elemental type change, offsets cannot be part of the type in general because sizeof(srcType) != sizeof(dstType).

Howerver, offset is a poorly chosen term for this purpose and is renamed to byte_shift.

Additionally, for all intended purposes, trying to support non-identity layouts for this op does not bring expressive power but rather increases code complexity.

This revision simplifies the existing semantics and implementation.
This simplification effort is voluntarily restrictive and acts as a stepping stone towards supporting richer semantics: treat the non-common cases as YAGNI for now and reevaluate based on concrete use cases once a round of simplification occurred.

Diff Detail

Event Timeline

Herald added a project: Restricted Project. · View Herald Transcript

Note the tests are very much WIP but early comments on the update to Ops.td is what I am looking for.

mehdi_amini added inline comments.May 6 2020, 8:01 PM
mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
2997

3 * i8 is what you mean here I think? I read what you wrote as "3 x pointers-size"

3007

The part about function boundaries and "the offset from the allocated pointer is not available in the returned view." isn't clear to me. In particular this seems to be referring to some lowering specific aspects.

3009–3010

Seems invalid now.

3010–3011

The returned memref has non-identity map which you forbid in the description above.

3011

All the part about aliasing isn't clear to me either, it would benefit from examples of the attributes you refer to here.

3016

I don't know what this whole paragraph intends to convey, but I'm not sure it really describes the operation anyway.

3029

What kind of template implementations (instantiations?) require this?

mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
2679

The doc says that the returned memref has 0 offset and contiguous layout (i.e. empty or identity layout map).
Seems like this code above isn't useful, am I misunderstanding that this will always look into an identity map?

nicolasvasilache marked 11 inline comments as done.

Finish updating tests.

nicolasvasilache marked 2 inline comments as done.May 7 2020, 8:16 AM
nicolasvasilache added inline comments.
mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
3007

Dropping this part as it is not strictly related to this op's semantics.

3011

Dropping this part as it is not strictly related to this op's semantics.

3016

Dropping this part as it is not strictly related to this op's semantics.

3029

Added as a comment.

mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
2679

It does extract the mixed static-dynamic strides from the sizes + identity layout.
The strides are used below to fill the descriptor.

nicolasvasilache edited the summary of this revision. (Show Details)May 7 2020, 8:21 AM
mravishankar added inline comments.
mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
2994

There is another problem w.r.t to view operation w.r.t to lowering to SPIR-V dialect. This is doing a type-cast. The SPIR-V spec is very restrictive in pointer casts it allows to the effect that current plan is to not use pointer casts at all within the SPIR-V dialect. While it is a SPIR-V restriction, I am not sure what the type casting here gives us. Specifically this is always type-casting (cause the base memref is i8). The requirement of creating a multi-dimension memref can be done using an AllocOp directly. If the need is to model aliasing between different uses you can use a memref_cast. The memref_cast can also be done for changing element type. That would then be an "opt-in". You do it only when you need it. For now I am not sure whether we need the ViewOp at all.

nicolasvasilache retitled this revision from [WIP][mlir] RFC - Simplify and better document std.view semantics to [mlir] Simplify and better document std.view semantics.May 7 2020, 11:40 AM
nicolasvasilache edited the summary of this revision. (Show Details)
nicolasvasilache marked an inline comment as done.

Update doc

nicolasvasilache marked 2 inline comments as done.May 7 2020, 12:15 PM
nicolasvasilache added inline comments.
mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
2994

There are a few moving pieces here but the use case this wants to serve is a single bigger alloc from which multiple smaller pieces are extracted, alias or not and memory chunks that can be reused with linear allocation schemes.

Any op that casts from a small type to a bigger type will have similar issues if it wants to shift the base address by quantities that are not multiples of the bigger type size. Then there will also be alignment considerations and other fun stuff.

Re. using the op in particular scenarios I view this as a separate concern from the fact that the implementation of the op did not match the semantics and that the semantics and description needed to be updated to distinguish between offset and byte_shift.

nicolasvasilache marked an inline comment as done.May 7 2020, 12:25 PM
timshen added inline comments.May 7 2020, 1:03 PM
mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
2985–2991

"contiguous memref" -> "slice"? To me "contiguous" means "no gaps between the accessed bytes", but it doesn't imply identity layout. Coming from Python/C++ background, "slice" implies identity layout.

mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
2703

If the offset is 0, would it work by not calling setOffset() at all?

nicolasvasilache marked 4 inline comments as done.May 7 2020, 1:19 PM
nicolasvasilache added inline comments.
mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
2985–2991

slice has potential conflicts in MLIR, there is a rank-reducing slice op in Linalg that is likely to be ported to std or to be folded within subview.

How about "contiguous memref with empty or identity layout" ?

mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
2703

If we don't set the offset we will have uninitialize memory that can be propagated further through subviews or function calls: the descriptor created here will be used in various ways and the offset will be used later in load/stores etc.

The change looks fine to me. As mentioned in commit message, some of the uses need to be re-evaluated (the one im hitting is the use of view in memory promotion)

mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
2994

Thanks for clarification. The view op as stated itself could be lowered to SPIR-V, but the issue is the backing allocation. The allocation type will have to be "deduced" bsaed on its type, and then fail if there are multiple uses with different types. Thats an OK-ish solution, but not a clean solution for sure. Maybe the uses of view op can be looked into and avoided (in memory promotion for example).
No further comments on this now. Thanks!

mravishankar accepted this revision.May 7 2020, 1:41 PM
This revision is now accepted and ready to land.May 7 2020, 1:41 PM
timshen added inline comments.May 7 2020, 1:54 PM
mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
2985–2991

Sure, but other occurrences of "contiguous" will have to be lengthened with "empty or identity layout" as well.

timshen accepted this revision.May 7 2020, 1:54 PM
nicolasvasilache marked 2 inline comments as done.

Update

This revision was automatically updated to reflect the committed changes.
rriddle added inline comments.May 27 2020, 12:00 PM
mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
3036

Why not just sizes()?

mlir/lib/Dialect/StandardOps/IR/Ops.cpp
2778

Just stream it:

p << ... << op.byte_shift() << ....

I would also expect that this could now use the declarative format now that the weird 'dynamicOffset' thing is removed.

2795

nit: Can you move the viewType.getAffineMaps() to a local variable?