This is an archive of the discontinued LLVM Phabricator instance.

[mlir][linalg] Fold ExtractSliceOps during tiling.
ClosedPublic

Authored by gysit on Sep 10 2021, 5:56 AM.

Details

Summary

Add the makeComposedExtractSliceOp method that creates an ExtractSliceOp and folds chains of ExtractSliceOps by computing the sum of their offsets and by multiplying their strides.

Diff Detail

Event Timeline

gysit created this revision.Sep 10 2021, 5:56 AM
gysit requested review of this revision.Sep 10 2021, 5:56 AM
gysit updated this revision to Diff 371974.Sep 10 2021, 11:22 AM

Fix windows build.

mravishankar requested changes to this revision.Sep 12 2021, 12:08 PM

Just a few comments.

mlir/lib/Dialect/Linalg/Utils/Utils.cpp
206

I have written this function multiple times. Need a common place for it. I think its complicated since it requires standard dialect so any place this is put needs to also add dependency on standard dialect.

219

Not sure doing this recursively in a loop is a good idea. Maybe just do one step and allow the pattern rewriter to apply it multiple times?

221

Why? This is just folding the offsets and the strides. The type should still remain the same right. So you should be able to handle this?

228

I am not convinced that you can just add the offsets. I think you can do that only if the strides are 1 (though I havent given this deep thought, just a first impression).

I would just simplify all of this and check for all strides in the producer and consumer to be unit strides and bail if they arent. I dont think we have a case with strides not being 1 anyway.

Meta point: We should just drop strides from subviews. Do we ever use non-unit strides?

This revision now requires changes to proceed.Sep 12 2021, 12:08 PM
gysit added inline comments.Sep 12 2021, 11:47 PM
mlir/lib/Dialect/Linalg/Utils/Utils.cpp
206

I tried to reuse an existing implementation but all of them introduce strange dependencies. Also a standard dialect implementation probably requires more functionality in the sense that we would have to support non integer types etc.

221

The idea is to make sure the producer is not rank reducing. It it is there would be a type mismatch.

228

Good point! I think you are right regarding the strides and adding offsets. The two offsets can potentially have different strides which cannot be handled properly in one extract slice. I will check for stride one then.

springerm added inline comments.
mlir/lib/Dialect/Linalg/Utils/Utils.cpp
206

Just fyi. There is getAsOpFoldResult etc. in StaticValueUtils, which are related to this. I ran into the same issue with "dependency on std" when I added these, which is why I couldn't add this function.

Anyway... I don't know how to solve this in a nice way either.

gysit added inline comments.Sep 13 2021, 12:18 AM
mlir/lib/Dialect/Linalg/Utils/Utils.cpp
206

StandardOps/Utils/Utils.h may be an option? But then the idea seems to be to remove std...

gysit updated this revision to Diff 372222.Sep 13 2021, 5:41 AM

Address comments.

gysit updated this revision to Diff 372238.Sep 13 2021, 6:38 AM

Cleaner version of OpFoldResult to Value helper.

nicolasvasilache accepted this revision.Sep 13 2021, 7:36 AM
nicolasvasilache added inline comments.
mlir/lib/Dialect/Linalg/Utils/Utils.cpp
203

can you early exit and avoid increasing nesting logic?

209

Just checking equality of the strides of the 2 ops would be enough here.
It would also capture rank preserving.

Re. "do we need something else than stride 1": in practice today no but things like dilation in convolutions are one of the envisioned use cases.

223

Could you provide a version of makeComposedAffineApply that works with OpFoldResult and simplify the caller?

gysit updated this revision to Diff 372269.Sep 13 2021, 8:47 AM

Address comments.

gysit marked an inline comment as done.Sep 13 2021, 9:02 AM
gysit added inline comments.
mlir/lib/Dialect/Linalg/Utils/Utils.cpp
209

After some more thought I think the relevant information are the producer strides? If they are one then both offsets are expressed using the same strides.

223

After some more though I think my last version was wrong as well. If I am not mistaken the best solution for now is to check the producer strides are one. I think this is a necessary condition to guarantee the producer and consumer offsets are expressed in the same stride?

In theory we could also handle other producer strides by multiplying the consumer offset by the producer stride before adding the offsets for the folding. Or am I wrong again here?

mlir/lib/Dialect/Linalg/Utils/Utils.cpp
209

Ah yes my apologies .. strides in subX operations compose (i.e. the op can strictly subsample its input).

Resulting strides should be the product of strides.
Resulting sizes should be the consumer sizes.
Result offset should consumer_offset + producer_offset * consumer strides.

nicolasvasilache requested changes to this revision.Sep 13 2021, 11:48 AM
This revision now requires changes to proceed.Sep 13 2021, 11:48 AM
mlir/lib/Dialect/Linalg/Utils/Utils.cpp
209

Sigh .. I meant:

Result offset should be producer_offset + consumer_offset * producer_strides.

Here is the code that implements the lowering to LLVM (replace producer by "sourceMemRef"):
https://sourcegraph.com/github.com/llvm/llvm-project/-/blob/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp?L1307

Now as Mahesh pointed out, this is not well tested on actual use cases so maybe failing if strides are != 1 is the most pragmatic thing to do right now ..

gysit updated this revision to Diff 372441.Sep 14 2021, 2:20 AM

Address comment.
In particluar:

  • Support unit-strides only.
nicolasvasilache accepted this revision.Sep 14 2021, 2:47 AM
This revision was not accepted when it landed; it landed in state Needs Review.Sep 14 2021, 4:51 AM
This revision was automatically updated to reflect the committed changes.