This expose a lambda control instead of just a boolean to control unit dimension folding.
Note that it is not a completely NFC change as it modified the default behavior of populateElementwiseOpsFusionPatterns to always allow reshape folding. This however gives more control to user to pick a good heuristic.
Folding reshapes helps fusion opportunities but may generate sub-optimal generic ops.
Details
Diff Detail
Event Timeline
mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h | ||
---|---|---|
89 | Do we need a different type? the below uses OpResult and OpOperand we could use the same signature | |
mlir/lib/Dialect/Linalg/Transforms/FusionOnTensors.cpp | ||
1436 | I understand why this is done (and I kind of like it too). But I would move this logic into the populate* methods below. |
mlir/lib/Dialect/Linalg/Transforms/FusionOnTensors.cpp | ||
---|---|---|
1479 | Restating comment from above more clearly. It would be better to keep the default behavior consistent with allowFoldingUnitDimReshapes = false. So just calling populateFoldReshapeOpsByExpansionPatterns should set the controlFoldingReshapes to a function that effectively disables fusion for cases where the expansion adds unit-dimensions. THe check to see if this expansion is adding unit-dimensions is failry involved. I'd like to keep it as a default behavior, and wrapped within this populate* method. If a client wants to override it then thats upto them... |
THanks Thomas. Just one last comment.
mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h | ||
---|---|---|
31 | I think it is better to have the signature as bool(const OpResult &producer, const OpOperand &operand). As it currently stands just OpOperand is sufficient, but for sake of consistency and future-proof ness it would be better to have the result and operand explicit (producer and consumer). Also it is consistent with ControlElementwiseOpsFusionFn` signature (I am OK if you want to rename it). Lesser cognitive overhead in API. | |
89 | See above comment about signature. |
mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h | ||
---|---|---|
31 | I don't understand why we need to pass producer and consumer. OpOperand contains both the operand Value as well as the consumer op with getOwner(). What information are we missing? This let use get the ReshapeOp as well as the linalgOp consuming and the operand index. |
mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h | ||
---|---|---|
31 | Its more ergonomics. You are given a producer and a consumer in the call back. You dont need to have all client have to do operand.cast<OpResult>() to get the producer. OpResult and OpOperand seemed like the best choice, cause you get the result number in the former and the argument number in the latter directly. |
mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h | ||
---|---|---|
31 | Changed it. |
mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h | ||
---|---|---|
31 | Thanks! One Nit: you dont need a different using here. You could just make this ControlElementwiseOpsFusionFn . I am not holding this up for that, but would be good to just drop this typedef. |
mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h | ||
---|---|---|
31 | Sure, I switch to use ControlElementwiseOpsFusionFn |
I think it is better to have the signature as bool(const OpResult &producer, const OpOperand &operand). As it currently stands just OpOperand is sufficient, but for sake of consistency and future-proof ness it would be better to have the result and operand explicit (producer and consumer). Also it is consistent with ControlElementwiseOpsFusionFn` signature (I am OK if you want to rename it). Lesser cognitive overhead in API.