This is an archive of the discontinued LLVM Phabricator instance.

[mlir] Support alignment in LLVM dialect GlobalOp
ClosedPublic

Authored by dpotop on Apr 28 2021, 2:40 PM.

Details

Summary

First step in adding alignment as an attribute to MLIR global definitions. Alignment can be specified for global objects in LLVM IR. It can also be specified as a named attribute in the LLVMIR dialect of MLIR. However, this attribute has no standing and is discarded during translation from MLIR to LLVM IR. This patch does two things: First, it adds the attribute to the syntax of the llvm.mlir.global operation, and by doing this it also adds accessors and verifications. The syntax is "align=XX" (with XX being an integer), placed right after the value of the operation. Second, it allows transforming this operation to and from LLVM IR. It is checked whether the value is an integer power of 2.

Diff Detail

Event Timeline

dpotop created this revision.Apr 28 2021, 2:40 PM
dpotop requested review of this revision.Apr 28 2021, 2:40 PM
rriddle added inline comments.Apr 28 2021, 2:45 PM
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
435

nit: Drop all of the mlir::, you are already in the mlir namespace.

435

MLIR uses camelCase variable names.

436

Can you run clang-format?

438

Is the template necessary here?

439

Drop the llvm:: here, APInt is exported in the mlir namespace.

439–441

I think getUInt currently asserts that the type is unsigned, though I don't think it should.

Can you also add test (and support if needed) in the other direction? (LLVM IR->MLIR)

(also see https://mlir.llvm.org/getting_started/Contributing/#commit-messages for the commit message format)

Le mer. 28 avr. 2021 à 23:52, Mehdi AMINI via Phabricator <
reviews@reviews.llvm.org> a écrit :

mehdi_amini added a comment.

Can you also add test (and support if needed) in the other direction?
(LLVM IR->MLIR)

I was not aware that there is a way to go LLVM IR->MLIR. Is this
"mlir-translate --import-llvm"?
I will try to do it (why is this important?).

(also see
https://mlir.llvm.org/getting_started/Contributing/#commit-messages for
the commit message format)

Thanks. I noted the bad format.

D.

Repository:

rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION

https://reviews.llvm.org/D101492/new/

https://reviews.llvm.org/D101492

You also miss a test in mlir/test/Target/LLVMIR/llvmir.mlir ; the test you modified is only MLIR->MLIR and does not exercise the translation.

For LLVM IR to MLIR the test is mlir/test/Target/LLVMIR/import.ll

Can you please separate the commit title from the summary?

dpotop updated this revision to Diff 341419.Apr 29 2021, 12:07 AM

Corrections and additions to D101492: adding alignment to the LLVMIR dialect

I have made the required corrections and applied clang-format.
I have also added the round-trip LLVMIR->MLIR and the tests.

ftynse retitled this revision from First step in adding alignment as an attribute to MLIR global definitions. Alignment can be specified for global objects in LLVM IR. It can also be specified as a named attribute in the LLVMIR dialect of MLIR. However, this attribute has no... to [mlir] Support alignment in LLVM dialect GlobalOp.Apr 29 2021, 12:12 AM
ftynse edited the summary of this revision. (Show Details)
ftynse requested changes to this revision.Apr 29 2021, 12:15 AM

Could you please specify the alignment in the definition of the op, similarly to how it's done on, e.g., AllocaOp - https://github.com/llvm/llvm-project/blob/9363aa90bfe6f73df105799abc55bb74d4f186bf/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td#L294. Having random unverified attributes attached to an operation isn't really robust.

This revision now requires changes to proceed.Apr 29 2021, 12:15 AM
dpotop updated this revision to Diff 341470.Apr 29 2021, 4:36 AM

Support alignment in LLVM dialect GlobalOp - add dedicated syntax, accessors

I have added a dedicated syntax to the alignment attribute,
and dedicated accessor routines.
This resulted in changes to multiple files.

dpotop updated this revision to Diff 341575.Apr 29 2021, 10:37 AM

Correcting formatting issues signalled by clang-tidy.

mehdi_amini accepted this revision.Apr 29 2021, 10:51 AM
mehdi_amini added inline comments.
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
441

Nit: avoid duplicating isa+cast, instead the usual idiom is:

IntegerAttr alignAttr = rawAlignAttr.dyn_cast<IntegerAttr>();
if (!alignAttr) 
  return emitError(op.getLoc(),
                               alignment constant should be an integer");
mehdi_amini added inline comments.Apr 29 2021, 10:57 AM
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
1031

The doc does not match the implementation.

Do we need these two method by the way? Why aren't the usual ODS generate accessors enough?

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
441

Also since this is part of the verifier, you don't even need to check. The fast that it is define in ODS should give you a direct accessor: llvm::Optional<uint64_t> align();. on the GlobalOp
(and also a mlir::IntegerAttr alignAttr() accessor).

ftynse added inline comments.Apr 29 2021, 11:05 AM
mlir/examples/toy/Ch6/mlir/LowerToLLVM.cpp
143

Nit: the usual syntax is /*align=*/. Also, you shouldn't be needing to pass null objects for trailing optional attributes.

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
910

Bikeshedding: other ops in this dialect use $alignment, I'd prefer this to be consistent and also use $alignment.

987–988

We probably want a verifier for this.

1016–1018

You can use CArg<"Attribute", "Attribute()">:$align here to give the generated argument the default value. This will let you clean up all the places that are passing Attribute() and don't care about alignment.

1031

Nit: this comment doesn't match what the function do, i.e., they don't return an _attribute_.

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
1290–1292

Other ops in this dialect use the generic attribute dictionary syntax to specify alignment, I think this can do the same and not bother with custom syntax.

1575–1576

Parser should already report an error if any of the calls to parser.parse* fails. We usually just return failure() here and don't emit a second error.

Also, we usually have 100% coverage for user-visible error messages. There is a test suffixed with "invalid" that checks them. (I expect this message, if not the surrounding code, to disappear, so you don't need to add the test).

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
435

Now that alignment attribute is declared in the op spec, you can use op.align(). This is preferred over stringly attribute access.

437–439

There's no need to check this or to emit an error, the generated verifier will have ensured that valid ops have the integer attribute.

ftynse added inline comments.Apr 29 2021, 11:25 AM
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
1016–1018

Actually, on a second thought, consider taking CArg<"unsigned", "0"> and create the attribute in the builder body. This way, the caller doesn't need to bother with creating the attribute and cannot accidentally give you one of a wrong type.

dpotop updated this revision to Diff 341612.Apr 29 2021, 12:50 PM
dpotop marked 10 inline comments as done.

Code corrections and improvements in response to comments.

mehdi_amini accepted this revision.Apr 29 2021, 1:07 PM

Still LGTM :)
(but you should likely wait for Alex to confirm)

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
1293

(nit: remove spurious braces in such cases)

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
438

(here as well)

dpotop edited the summary of this revision. (Show Details)Apr 29 2021, 1:08 PM

Can you run clang-format?

mlir/examples/toy/Ch7/mlir/LowerToLLVM.cpp
143

Missed this here? Same comment as Ch6.

mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp
41

Same here.

mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
2305

and here.

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
1577

There is a helper function in LLVM for this, named something like IsPowerOf2_32.

2364

Drop the space after the comment.

mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
479

nit: Comments should be proper sentences (punctuation, etc.)

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
434

Same here.

435

nit: Spell out auto here.

dpotop marked 6 inline comments as done.Apr 29 2021, 1:15 PM
dpotop added inline comments.
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
910

I have a problem with this, because the IR keyword is "align". Then, one cannot use both the native syntax (with "align") and the general-purpose attribute syntax (with "alignment"). I find this useful. BTW, my code is not the only one where "align" is used. There are some operations (such as llvm.intr.coro.id) which use "align" instead of "alignment".

1016–1018

It was a choice to write all the "Attribute()" manually. I already modified large bases of code, and *not* having default values is helpful, because you have to review all points of use. Let me know if you require this change, or if it's optional.

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
1290–1292

I don't know how to use the dictionary - I have tried using getAlignAttrName(), and it is not defined, so I guess I should put the name into the dictionary somehow. And since other attributes are left textual...

dpotop updated this revision to Diff 341627.Apr 29 2021, 1:37 PM
dpotop marked 10 inline comments as done.

Further fancy formatting.

Lots of "done" comments.

ftynse accepted this revision.Apr 29 2021, 2:38 PM

LGTM with my comments addressed.

Please note that I will change ops in the LLVM dialect to be more consistent if this becomes necessary, I regularly touch this dialect.

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
910

I am fine with anything as long as it's consistent. There's one operation that uses $align, and does so for an _operand_ rather than attribute which could justify the difference, and several that use $alignment. I would have gone with the majority rule, or with the similarity rule (how likely one is going to try transferring the "style" of operation from one memory operation to another vs. from coroutine operation to memory operation?)

I won't block you on this because I strongly dislike bikeshedding, but I would be happier with a more consistent naming scheme.

1016–1018

This choice arguably makes life harder for everybody who will want to construct the op in the future. Yes, you got to review all points of use thanks to it. Now this change has served its purpose (you have reviewed all uses) and is no longer justified.

In any case, I will insist on at least changing it to not be generic "Attribute". Please use an unsigned instead.

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
1290–1292

Just rely on the printOptionalAttrDict before and drop the custom printing/parsing code. MLIR supports an open set of attribute and will print them in the dictionary unless you instruct it not to, which you currently do by putting "align" in the list below. If you don't, it will be printed as llvm.mlir.global @name(...) { align = 32 }.

This revision is now accepted and ready to land.Apr 29 2021, 2:38 PM
dpotop added a comment.EditedApr 29 2021, 11:40 PM

No problem for the other modifications, I'll implement them.
However, I have a problem with the following one.

Le jeu. 29 avr. 2021 à 23:38, Alex Zinenko via Phabricator <
reviews@reviews.llvm.org> a écrit :

Comment at: mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp:1277-1279
+ if (op.hasAlign()) {
+ p << " align=" << op.getAlign() << " ";

+ }

dpotop wrote:

ftynse wrote:

Other ops in this dialect use the generic attribute dictionary syntax

to specify alignment, I think this can do the same and not bother with
custom syntax.

I don't know how to use the dictionary - I have tried using

getAlignAttrName(), and it is not defined, so I guess I should put the name
into the dictionary somehow. And since other attributes are left textual...
Just rely on the printOptionalAttrDict before and drop the custom
printing/parsing code. MLIR supports an open set of attribute and will
print them in the dictionary unless you instruct it not to, which you
currently do by putting "align" in the list below. If you don't, it will be
printed as llvm.mlir.global @name(...) { align = 32 }.

Is this accepted in MLIR, to have for one attribute a dedicated accessor but
general-purpose syntax/printing/parsing? The general-purpose approach is
what I had done in the beginning. Maybe it deserved some verifications, but
these did not require significant changes in my initial code. The dedicated syntax is
what I implemented yesterday. But a mix of the two just seems off. I'll do it if
you maintain your request, but it just seems off. I'd prefer understanding how to
correctly use the dictionary instead. :)

Dumitru

ftynse requested changes to this revision.Apr 30 2021, 1:01 AM

I would think that I have enough experience in MLIR and in the LLVM dialect in particular to expect my requests to be interpreted as something that is not only accepted in this part of the codebase but indeed highly recommended. I am still the largest contributor to the file you are editing, https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td...

Yes, it is perfectly fine not to have custom syntax for attributes defined in the operation. So is not having custom syntax at all for the operation. There is absolutely no implied connection whatsoever between how the custom syntax looks like and the API provided on the operation. The general pattern, although it may vary between dialects, is to consider supporting custom syntax for mandatory or frequently used attributes, and keep everything else in the dictionary syntax. Alignment is not mandatory, and doesn't seem that frequently used if we survived without it for over a year that this op exists. The problem you are creating by insisting on not following what the rest of the dialect does is as follows. One knows that to set alignment in memory operations one has to do something like llvm.load %address { alignment = 32 } : !type. This sounds logical to try doing exactly the same on a global llvm.global @name(initializer) { alignment = 32 } : !type. It will fail because this code requires one to use align=32 instead. This kind of small things make the programming interface feel unintuitive if not hostile, and that's why I care about consistency. Now, I am sensitive to your argument that LLVM IR uses align and not alignment and my consistency argument can also apply. All ops should use align to be consistent with LLVM IR and with each other. But let's have the same syntax even if different attribute name at the very least!

This revision now requires changes to proceed.Apr 30 2021, 1:01 AM
dpotop updated this revision to Diff 344409.May 11 2021, 8:17 AM

Further corrections to support alignment in LLVMIR dialect GlobalOp

Corrected the syntax to only use the standard form for the
alignment attribute (no dedicated syntax) and to use the
attribute name "alignment", as opposed to "align" or "llvm.align".
Also updated the test cases and added a new one that checks that
alignment is verified.

ftynse accepted this revision.May 11 2021, 8:42 AM

Thanks!

This revision is now accepted and ready to land.May 11 2021, 8:42 AM
dpotop updated this revision to Diff 344477.May 11 2021, 10:44 AM

Support alignment in LLVM dialect GlobalOp

Corrected test case.

Thank you for the help!
Now I'll be moving to the memref dialect to add the attribute to the global
operation, and then complete the lowering to LLVMIR.
Dumitru

Le mar. 11 mai 2021 à 17:42, Alex Zinenko via Phabricator <
reviews@reviews.llvm.org> a écrit :

ftynse accepted this revision.
ftynse added a comment.
This revision is now accepted and ready to land.

Thanks!

Repository:

rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION

https://reviews.llvm.org/D101492/new/

https://reviews.llvm.org/D101492

I reformatted your commit before landing.

This revision was landed with ongoing or failed builds.May 12 2021, 12:07 AM
This revision was automatically updated to reflect the committed changes.