Add canonicalization to replace use of the result of a linalg
operation on tensors in a dim operation, to use one of the operands of
the linalg operations instead. This allows the linalg op itself to be
deleted when all its non-dim uses are removed (say through tiling, etc.)
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Also @pifon2a
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | ||
---|---|---|
2117 | prevent | |
2131 | This revision introduces OpInterface support for getLoopsToShapesMap and getShapesToLoopsMap and dropped special-case logic. Let's please use those instead of reintroducing special-case logic, this will be more future-proof. This should prob take the form of a new interface method Value inferDimFromInputs(unsigned resultIdx, unsigned dim) which:
e.g. assume some hypothetical op that resembles matmul with a twist: O(i + j, j) += A(i, k) * B(k, j):
Assume you wanted the expression of dim res, 0 (i.e. i + j, a.k.a dim A, 0 + dim B, 1). Step 1. IDX = 4 In step 4. you will prob need to adjust to only take the input operands. Does this make sense ? |
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | ||
---|---|---|
2165–2166 | nit: use auto because there is a dyn_cast. https://llvm.org/docs/CodingStandards.html#use-auto-type-deduction-to-make-code-more-readable |
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | ||
---|---|---|
2131 | I think it makes sense. But there is a corner case here that might make the pattern rewriter go into a loop, and it doesnt happen today. Take an op where the loop shape actually depends on the shape of the output. %cst = constant 0.0 : f32 %1 = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>], iterator_types = ["parallel", "parallel"]} ins() { ^bb0(): linalg.yield %cst : f32 } -> tensor<?x?xf32> Today, the loop computation fails to get the right loop shape for such ops (the method createLoopRanges I think will throw an error cause createFlatListOfOperandDims does not append the shape of the results that makes affineApplyMapToValues(b, loc, getShapesToLoopsMap(), createFlatListOfOperandDims() fail due to mismatch in number of values passed and numdims of the map. (The next CL in the stack fixes that issue). |
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | ||
---|---|---|
91 | Thats true, but the signature of Optional makes it explicit that this can return llvm::None. Its easier to follow that. We can dcoument that it returns nullptr on failure, but that might just be easier to miss. This makes it more explicit. WDYT? | |
116–120 | I feel like that would make the logic more complicated. This is easier to follow IMO. Will leave it as is if thats OK. |
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | ||
---|---|---|
91 | Yes, you are right on that. It is indeed more explicit. Personally, I don't have a strong feeling on this because I know Value could be nullptr and it could ends up with an assertion at some point. It already has Optional semantic to me. Another point is that Optional introduces a bit more memory usage (ie sizeof(bool) and padding may be added). If Value itself carries this information and people commonly use it, I'd prefer returning nullptr on failure. However, I went through some usage, and found that some people use Optional<Value> and some people use Value directly. There is no convention here. So I'll leave the decision to you. | |
116–120 | Sure, both are okay to me. I just feel that the comment states what it's doing and it looks simpler to me. But both looks good to me. |
Adapting this to work with current setup of linalg operations. The
specifics might change based on
https://llvm.discourse.group/t/linalg-and-shapes/2421.
Going through my unreviewed stack, note that with the revamp of linalg on tensors @pifon2a sent a diff today that implements the functionality with out tensors,
Ok, Ill leave it upto you if this needs to be pushed in. I rebased it on top of the linalg on tensors changes. It still describes the shape in terms of "ins". THat might still be worth it. PTAL and let me know.
ok, my apologies, this looks great, I'll do a proper review in a bit but consider it landed :)
mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | ||
---|---|---|
134 | Not needed anymore after interface method is added. |
IIRC, Value can be nullptr, so we don't need optional here?