This is an archive of the discontinued LLVM Phabricator instance.

[MLIR][Standard] Lower `std.dim` with dynamic dimension operand to LLVM
ClosedPublic

Authored by frgossen on Jun 15 2020, 3:21 AM.

Details

Summary

Implement the missing lowering from std.dim to the LLVM dialect in case of a
dynamic dimension.

Diff Detail

Event Timeline

frgossen created this revision.Jun 15 2020, 3:21 AM
Herald added a project: Restricted Project. · View Herald Transcript
pifon2a accepted this revision.Jun 15 2020, 4:14 AM
pifon2a added inline comments.
mlir/test/Conversion/StandardToLLVM/convert-dynamic-memref-ops.mlir
416

please, capture !llvm<"{ float*, float*, i64, [3 x i64], [3 x i64] }"> as [[DESCR_TY]] and use everywhere below.

This revision is now accepted and ready to land.Jun 15 2020, 4:14 AM
herhut added inline comments.Jun 15 2020, 4:30 AM
mlir/test/Conversion/StandardToLLVM/convert-dynamic-memref-ops.mlir
427

Does this work when translated to LLVM proper? (You can check with mlir-translate). I think the argument to a GEP needs to be a pointer but in this case it is a value.

frgossen updated this revision to Diff 270718.Jun 15 2020, 4:36 AM
frgossen marked an inline comment as done.

Apply suggestion

ftynse requested changes to this revision.Jun 15 2020, 4:52 AM

Have you checked that bare-pointer calling convention also works?

mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
574

Value is a descriptor (LLVM struct type), you need to extractvalue from it before doing GEP.

mlir/test/Conversion/StandardToLLVM/convert-dynamic-memref-ops.mlir
411

Nit: I think "dynamic-memref-ops" was intended for ops working on dynamic memrefs, i.e. those with dynamic dimensions. This is not the case here.

416

Cool trick!

This revision now requires changes to proceed.Jun 15 2020, 4:52 AM
frgossen updated this revision to Diff 270813.Jun 15 2020, 12:02 PM
frgossen marked 4 inline comments as done.

Fix getelementptr issue.

mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
574

I see. Unfortunately not even the sizes in the MemRefDescriptor are a pointer here :/

mlir/test/Conversion/StandardToLLVM/convert-dynamic-memref-ops.mlir
427

The new version does. It copies everything to stack-allocated memory. Is this what you meant earlier today? I checked this manually with mlir-translate. Should that be reflected in this test, i.e. should I add the corresponding //RUN: ... statement?

Have you checked that bare-pointer calling convention also works?

How can I do that?

mlir/test/Conversion/StandardToLLVM/convert-dynamic-memref-ops.mlir
416

Facepalm .. Thanks much @pifon2a MUCH better!

frgossen marked an inline comment as done.Jun 15 2020, 12:55 PM
herhut accepted this revision.Jun 16 2020, 1:06 AM

In the long run we need a better way to do this so that we only materialize the descriptor once if needed. Until then, this will work (with some nits).

We can land this without restoring the stack for now.

mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
580

Does LLVM allow to store the entire array at once? I think store supports writing array-typed values.

One concern with this implementation is that it could fill up the stack quickly. Assume this gets called in a loop, then each iteration would put a new copy on the stack. We could use @llvm.stackrestore to limit the lifetime of the alloca'd memory. Not sure what that does to LLVMs optimizations, though.

@ftynse Should stackrestore be an operation in the llvm dialect? Seems handy to have it there.

ftynse accepted this revision.Jun 16 2020, 2:35 AM

In D81834#2092607, @ftynse wrote:
Have you checked that bare-pointer calling convention also works?

How can I do that?

mlir-opt -convert-std-to-llvmir="use-bare-ptr-memref-call-conv=1". There are also some tests for this flag.

Approving now, we can revise to the stacksave/stackrestore version in a separate commit. (It can be handy for dynamically-ranked memrefs as well).

mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
580

At some point, we were storing the entire descriptor on stack, and it did lead to stack explosion when called in a loop. I spent quite some time cleaning that up and now I am wary of alloca'ed memory for memrefs. I don't see another option here though.

The common trick I've seen is to put stack allocations in the entry block of the function. One cannot branch to that block so there will be no loops. And since this memory is only used in the immediately succeeding instructions and then discarded, we don't need any lifetime analysis to do the trick. This does not play well with pattern-based rewrites though...

@ftynse Should stackrestore be an operation in the llvm dialect? Seems handy to have it there.

Sure, it's an intrinsic, so it should be really easy to add.

This revision is now accepted and ready to land.Jun 16 2020, 2:35 AM
frgossen updated this revision to Diff 271021.Jun 16 2020, 3:42 AM

Address comments

frgossen updated this revision to Diff 271085.Jun 16 2020, 7:13 AM
frgossen marked 5 inline comments as done.

Address comments.

frgossen updated this revision to Diff 271100.Jun 16 2020, 7:51 AM

Remove test with bare-pointer calling convention

@ftynse, the new test case fails with bare-pointer calling convention because its argument is a dynamically shaped memref.
All the other tests with a dynamically shaped memref fail in the same way.
I tried the new test case with a statically shaped memref and it all works just fine.

Should I move the test case to another file, make the argument statically shaped, and test with bare-pointer calling convention?

mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
580

@herhut, can you check if this is what you had in mind?

Should I move the test case to another file, make the argument statically shaped, and test with bare-pointer calling convention?

No, just asking to double check. Thanks!

This revision was automatically updated to reflect the committed changes.