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.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
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 MonorepoCHANGES SINCE LAST ACTION
https://reviews.llvm.org/D101492/new/
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
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.
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.
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.
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"); |
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 |
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. |
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. |
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. |
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... |
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 }. |
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
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!
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.
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 MonorepoCHANGES SINCE LAST ACTION
https://reviews.llvm.org/D101492/new/
Nit: the usual syntax is /*align=*/. Also, you shouldn't be needing to pass null objects for trailing optional attributes.