[Mlir-commits] [mlir] [MLIR][linalg] Share external interface implementations to reduce build time (NFC) (PR #221814)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Sep 7 12:51:05 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-linalg

Author: Mehdi Amini (joker-eph)

<details>
<summary>Changes</summary>

The Linalg tiling and partial-reduction external models instantiate their operation-independent implementations for every registered structured op. Keep thin operation-specific external models, but inherit the implementations from non-template bases so the compiler emits and optimizes them only once. 

Assisted-by: Codex

---
Full diff: https://github.com/llvm/llvm-project/pull/221814.diff


1 Files Affected:

- (modified) mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp (+87-34) 


``````````diff
diff --git a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
index c84e5e50cb0e2..bbb23c00e5e19 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
@@ -200,31 +200,12 @@ validateTilingSemiAffineMaps(LinalgOp linalgOp, ArrayRef<OpFoldResult> sizes) {
 //===----------------------------------------------------------------------===//
 
 namespace {
-/// External model implementation of TilingInterface for LinalgOps. An external
-/// model implementation is used for now till the use of `TilingInterface` is
-/// on-par with the current Linalg tiling + fusion patterns. Once it is
-/// maybe possible to move this into the op-definition (though there are
-/// advantages to leaving it as an external model)
-template <typename LinalgOpTy>
-struct LinalgOpTilingInterface
-    : public TilingInterface::ExternalModel<LinalgOpTilingInterface<LinalgOpTy>,
-                                            LinalgOpTy> {
-  using Base =
-      TilingInterface::ExternalModel<LinalgOpTilingInterface<LinalgOpTy>,
-                                     LinalgOpTy>;
-  // Inherit the defaulted hint-bearing overloads; these ops do not require the
-  // hint (no inner tiles).
-  using Base::generateResultTileValue;
-  using Base::getIterationDomainTileFromOperandTiles;
-  using Base::getTiledImplementation;
-  using Base::getTiledImplementationFromOperandTiles;
-
-  /// Return the loop iterator type.
-  SmallVector<utils::IteratorType> getLoopIteratorTypes(Operation *op) const {
-    LinalgOpTy concreteOp = cast<LinalgOpTy>(op);
-    return concreteOp.getIteratorTypesArray();
-  }
-
+/// Operation-independent implementation shared by the external models for
+/// LinalgOps. External models are used for now until `TilingInterface` is
+/// on-par with the current Linalg tiling and fusion patterns. It may then be
+/// possible to move this into the op definitions, though there are advantages
+/// to leaving it as an external model.
+struct LinalgOpTilingInterfaceImpl {
   /// Return the iteration domain range.
   SmallVector<Range> getIterationDomain(Operation *op, OpBuilder &b) const {
     OpBuilder::InsertionGuard g(b);
@@ -517,6 +498,69 @@ struct LinalgOpTilingInterface
   }
 };
 
+template <typename LinalgOpTy>
+struct LinalgOpTilingInterfaceModel
+    : public TilingInterface::ExternalModel<
+          LinalgOpTilingInterfaceModel<LinalgOpTy>, LinalgOpTy>,
+      public LinalgOpTilingInterfaceImpl {
+  using ExternalModel =
+      TilingInterface::ExternalModel<LinalgOpTilingInterfaceModel<LinalgOpTy>,
+                                     LinalgOpTy>;
+
+  using LinalgOpTilingInterfaceImpl::generateScalarImplementation;
+  using LinalgOpTilingInterfaceImpl::getIterationDomain;
+  using LinalgOpTilingInterfaceImpl::getIterationDomainTileFromResultTile;
+  using LinalgOpTilingInterfaceImpl::getResultTilePosition;
+  using LinalgOpTilingInterfaceImpl::isOpFusableWithConsumerSlice;
+  using LinalgOpTilingInterfaceImpl::isOpFusableWithProducerSlices;
+
+  /// Return the loop iterator type without a dynamic LinalgOp interface lookup.
+  SmallVector<utils::IteratorType> getLoopIteratorTypes(Operation *op) const {
+    return cast<LinalgOpTy>(op).getIteratorTypesArray();
+  }
+
+  // Preserve the hint-bearing ExternalModel defaults while routing the
+  // no-hint overloads through the shared implementation.
+  using ExternalModel::generateResultTileValue;
+  FailureOr<TilingResult>
+  generateResultTileValue(Operation *op, OpBuilder &b, unsigned resultNumber,
+                          ArrayRef<OpFoldResult> offsets,
+                          ArrayRef<OpFoldResult> sizes) const {
+    return LinalgOpTilingInterfaceImpl::generateResultTileValue(
+        op, b, resultNumber, offsets, sizes);
+  }
+
+  using ExternalModel::getIterationDomainTileFromOperandTiles;
+  LogicalResult getIterationDomainTileFromOperandTiles(
+      Operation *op, OpBuilder &b, ArrayRef<unsigned> operandNumbers,
+      ArrayRef<SmallVector<OpFoldResult>> allOffsets,
+      ArrayRef<SmallVector<OpFoldResult>> allSizes,
+      SmallVectorImpl<OpFoldResult> &iterDomainOffsets,
+      SmallVectorImpl<OpFoldResult> &iterDomainSizes) const {
+    return LinalgOpTilingInterfaceImpl::getIterationDomainTileFromOperandTiles(
+        op, b, operandNumbers, allOffsets, allSizes, iterDomainOffsets,
+        iterDomainSizes);
+  }
+
+  using ExternalModel::getTiledImplementation;
+  FailureOr<TilingResult>
+  getTiledImplementation(Operation *op, OpBuilder &b,
+                         ArrayRef<OpFoldResult> offsets,
+                         ArrayRef<OpFoldResult> sizes) const {
+    return LinalgOpTilingInterfaceImpl::getTiledImplementation(op, b, offsets,
+                                                               sizes);
+  }
+
+  using ExternalModel::getTiledImplementationFromOperandTiles;
+  FailureOr<TilingResult> getTiledImplementationFromOperandTiles(
+      Operation *op, OpBuilder &b, ArrayRef<unsigned> operandNumbers,
+      ArrayRef<SmallVector<OpFoldResult>> allOffsets,
+      ArrayRef<SmallVector<OpFoldResult>> allSizes) const {
+    return LinalgOpTilingInterfaceImpl::getTiledImplementationFromOperandTiles(
+        op, b, operandNumbers, allOffsets, allSizes);
+  }
+};
+
 //===----------------------------------------------------------------------===//
 // External Model for implementing `PartialReductionInterface` for `LinalgOp`s.
 //===----------------------------------------------------------------------===//
@@ -655,12 +699,9 @@ static InitSliceInfo getInitSliceInfo(MLIRContext *context,
       partialReductionMap, initOperandShape);
 }
 
-/// External model implementation of PartialReductionInterface for
-/// LinalgOps.
-template <typename LinalgOpTy>
-struct LinalgOpPartialReductionInterface
-    : public PartialReductionOpInterface::ExternalModel<
-          LinalgOpPartialReductionInterface<LinalgOpTy>, LinalgOpTy> {
+/// Operation-independent implementation shared by the
+/// PartialReductionInterface external models for LinalgOps.
+struct LinalgOpPartialReductionInterfaceImpl {
   FailureOr<SmallVector<Value>> generateInitialTensorForPartialReduction(
       Operation *op, OpBuilder &b, Location loc, ArrayRef<OpFoldResult> sizes,
       const SetVector<unsigned> &reductionDims) const {
@@ -892,6 +933,18 @@ struct LinalgOpPartialReductionInterface
   }
 };
 
+template <typename LinalgOpTy>
+struct LinalgOpPartialReductionInterfaceModel
+    : public PartialReductionOpInterface::ExternalModel<
+          LinalgOpPartialReductionInterfaceModel<LinalgOpTy>, LinalgOpTy>,
+      public LinalgOpPartialReductionInterfaceImpl {
+  using LinalgOpPartialReductionInterfaceImpl::
+      generateInitialTensorForPartialReduction;
+  using LinalgOpPartialReductionInterfaceImpl::getPartialResultTilePosition;
+  using LinalgOpPartialReductionInterfaceImpl::mergeReductions;
+  using LinalgOpPartialReductionInterfaceImpl::tileToPartialReduction;
+};
+
 template <typename OpTy>
 static SmallVector<Range> getPackUnPackIterationDomain(OpTy op,
                                                        OpBuilder &builder) {
@@ -2008,9 +2061,9 @@ struct UnPackOpTiling
 
 template <typename OpType>
 static void registerOne(MLIRContext *ctx) {
-  OpType::template attachInterface<LinalgOpTilingInterface<OpType>>(*ctx);
-  OpType::template attachInterface<LinalgOpPartialReductionInterface<OpType>>(
-      *ctx);
+  OpType::template attachInterface<LinalgOpTilingInterfaceModel<OpType>>(*ctx);
+  OpType::template attachInterface<
+      LinalgOpPartialReductionInterfaceModel<OpType>>(*ctx);
 }
 
 /// Variadic helper function.

``````````

</details>


https://github.com/llvm/llvm-project/pull/221814


More information about the Mlir-commits mailing list