This will allow to model (variadic) reductions with this special op instead of
using GenericOp.
Details
- Reviewers
pifon2a nicolasvasilache rriddle dcaballe
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Thanks @akuegel for pushing in this direction!
I added a first round of comments.
Upon deeper inspection, I find that none of the tests exercise mixing ? and shape, I'd drop it from this PR for now and we can introduce later if needed (I suspect this would trigger discussions).
mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td | ||
---|---|---|
266 | getIteratorTypes ? | |
270 | getOutputs? | |
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | ||
1190 | getIteratorTypes? | |
1208 | I'd just start from getMultiDimIdentityMap and apply AffineMap dropResult(unsigned pos) for all getDimensions. Bonus points: impl AffineMap dropResults(ArrayRef<unsigned> pos) | |
1245 | do we want to just ignore stuff that is not what we expect ? | |
1306 | you seem to want to allow the mixing .. plz see my message below. | |
1314 | This allows mixing static and dynamic shapes, are you sure this is what you want? If so, this needs to be well-documented in the op semantics. If this is not the behavior you want, just do a.getShape() == b.getShape() ? Looking back at the RFC, we didn't discuss allowing implicit conversions to/from ?, could you comment on the tradeoffs? | |
1323 | same comment | |
1337 | can we use some Tablegen "confined" spec here and avoid reinventing? | |
1342 | feels like a generally useful Tablegen-level property to add (can be left for later). | |
1375 | if (getBody()->getNumArguments() != this->getNumOperands()) return emitOpError() << "mismatching number of operands and block arguments"; | |
1384 | // Note: zip iterates until the min length. for (auto [input, bbArg] :: llvm::zip(getInputs(), block->getArguments())) { if (input.getType().cast<ShapedType>().getElementType() != bbArg.getType()) return ... } | |
1398 | Same for (auto [..., bbArg] |
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | ||
---|---|---|
1314 | That's because we never discussed variadic reductions in the RFC. HLO allows having just "compatible" shapes among inputs and among outputs, but it is definitely not clear if it's needed. |
mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td | ||
---|---|---|
270 | Done, but this requires changing the DestinationStyleOpInterface. Please let me know whether I should move that change to a separate patch. Changing the name of this interface method would also require updates to users outside MLIR, e.g. tHLO in Tensorflow. | |
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | ||
1208 | I have added a dropResults method, however to make it easily usable for my case, I needed to use ArrayRef<int64_t>. To make both methods consistent, I also changed dropResult() to take int64_t. But maybe unsigned types are preferred here, and I should instead cast my int64_t ArrayRef? | |
1245 | Good point, I guess it makes sense to return a failure. Done. | |
1306 | Yes, not really necessary. I have removed this method. | |
1314 | Lets get rid of this. I think we don't need to allow mismatch of dynamic and static dimensions. | |
1337 | I guess you mean specifying dimensions as a ConfinedAttr? I tried the following: class IndexInBounds<int upperBound> : AttrConstraint<CPred<"llvm::all_of($_self.cast<::mlir::DenseI64ArrayAttr>" "().asArrayRef(), [](int64_t dim) { return dim >= 0 " "&& dim < " # upperBound # "; })">, "should be in the range [0, " # upperBound # "]">; ConfinedAttr<DenseI64ArrayAttr, [IndexInBounds<2>]>:$dimensions But in fact I cannot use a constant upper bound. How can I pass a dynamic upper bound (the input rank) to IndexInBounds? Is it even possible? And if it is not possible, should I just verify that each value is >= 0 and keep the other verification code inside the verify method? | |
1342 | So here I can see how it can be done as AttrConstraint. If I understand correctly, you would prefer if such a constraint is available for reuse. Where would be a good place for it in the code base? |
mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td | ||
---|---|---|
270 | Landed this change of the interface in https://reviews.llvm.org/rGdbf1fe5024e205f295ed0280d602d582774c39c9 |
Nice!
Minor comments (and maybe a bug)
mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td | ||
---|---|---|
270 | thanks for putting this in a separate patch! | |
mlir/include/mlir/IR/AffineMap.h | ||
254 | ++ | |
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | ||
1208 | Generally we should avoid unsigned as much as possible (see e.g. https://www.youtube.com/watch?v=Puio5dly9N8), there are a bunch of older APIs based on unsigned that will need to be cleaned up but avoiding to propagate that mistake is better, this is great as is. | |
1337 | Had the same issue in https://reviews.llvm.org/D130348 actually.. At the time, @Mogball wrote: This can be achieved with a derived attribute that uses the value of an optional attribute or some derived value | |
1342 | I would think something in OpBase.td would make sense to implement the "sorted" constraint. | |
1377 | wrong input/output mixing and you are getting lucky with the current tests :) ? |
Fix copy/paste bug in verify.
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | ||
---|---|---|
1337 | I also don't understand what is meant with derived attribute. | |
1342 | Ok, I will prepare a separate patch for that. | |
1377 | Good catch! I have adjusted the test for mismatched outputs a bit so that it would catch this bug. |
getIteratorTypes ?