xref: /llvm-project/mlir/test/lib/Dialect/Affine/TestAffineLoopParametricTiling.cpp (revision 4c48f016effde67d500fc95290096aec9f3bdb70)
13fef2d26SRiver Riddle //= TestAffineLoopParametricTiling.cpp -- Parametric Affine loop tiling pass =//
23fef2d26SRiver Riddle //
33fef2d26SRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43fef2d26SRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
53fef2d26SRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63fef2d26SRiver Riddle //
73fef2d26SRiver Riddle //===----------------------------------------------------------------------===//
83fef2d26SRiver Riddle //
93fef2d26SRiver Riddle // This file implements a test pass to test parametric tiling of perfectly
103fef2d26SRiver Riddle // nested affine for loops.
113fef2d26SRiver Riddle //
123fef2d26SRiver Riddle //===----------------------------------------------------------------------===//
133fef2d26SRiver Riddle 
143fef2d26SRiver Riddle #include "mlir/Dialect/Affine/IR/AffineOps.h"
15a70aa7bbSRiver Riddle #include "mlir/Dialect/Affine/LoopUtils.h"
163fef2d26SRiver Riddle #include "mlir/Dialect/Affine/Passes.h"
1736550692SRiver Riddle #include "mlir/Dialect/Func/IR/FuncOps.h"
183fef2d26SRiver Riddle 
193fef2d26SRiver Riddle using namespace mlir;
20*4c48f016SMatthias Springer using namespace mlir::affine;
213fef2d26SRiver Riddle 
223fef2d26SRiver Riddle #define DEBUG_TYPE "test-affine-parametric-tile"
233fef2d26SRiver Riddle 
243fef2d26SRiver Riddle namespace {
253fef2d26SRiver Riddle struct TestAffineLoopParametricTiling
2641574554SRiver Riddle     : public PassWrapper<TestAffineLoopParametricTiling,
2758ceae95SRiver Riddle                          OperationPass<func::FuncOp>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anon6f2407ba0111::TestAffineLoopParametricTiling285e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestAffineLoopParametricTiling)
295e50dd04SRiver Riddle 
30b5e22e6dSMehdi Amini   StringRef getArgument() const final { return "test-affine-parametric-tile"; }
getDescription__anon6f2407ba0111::TestAffineLoopParametricTiling31b5e22e6dSMehdi Amini   StringRef getDescription() const final {
32b5e22e6dSMehdi Amini     return "Tile affine loops using SSA values as tile sizes";
33b5e22e6dSMehdi Amini   }
3441574554SRiver Riddle   void runOnOperation() override;
353fef2d26SRiver Riddle };
36be0a7e9fSMehdi Amini } // namespace
373fef2d26SRiver Riddle 
383fef2d26SRiver Riddle /// Checks if the function enclosing the loop nest has any arguments passed to
393fef2d26SRiver Riddle /// it, which can be used as tiling parameters. Assumes that atleast 'n'
403fef2d26SRiver Riddle /// arguments are passed, where 'n' is the number of loops in the loop nest.
checkIfTilingParametersExist(ArrayRef<AffineForOp> band)41d98e6006SVimal Patel static LogicalResult checkIfTilingParametersExist(ArrayRef<AffineForOp> band) {
423fef2d26SRiver Riddle   assert(!band.empty() && "no loops in input band");
433fef2d26SRiver Riddle   AffineForOp topLoop = band[0];
443fef2d26SRiver Riddle 
4558ceae95SRiver Riddle   if (func::FuncOp funcOp = dyn_cast<func::FuncOp>(topLoop->getParentOp()))
46d98e6006SVimal Patel     if (funcOp.getNumArguments() < band.size())
47d98e6006SVimal Patel       return topLoop->emitError(
48d98e6006SVimal Patel           "too few tile sizes provided in the argument list of the function "
49d98e6006SVimal Patel           "which contains the current band");
50d98e6006SVimal Patel   return success();
513fef2d26SRiver Riddle }
523fef2d26SRiver Riddle 
533fef2d26SRiver Riddle /// Captures tiling parameters, which are expected to be passed as arguments
543fef2d26SRiver Riddle /// to the function enclosing the loop nest. Also checks if the required
553fef2d26SRiver Riddle /// parameters are of index type. This approach is temporary for testing
563fef2d26SRiver Riddle /// purposes.
57d98e6006SVimal Patel static LogicalResult
getTilingParameters(ArrayRef<AffineForOp> band,SmallVectorImpl<Value> & tilingParameters)58d98e6006SVimal Patel getTilingParameters(ArrayRef<AffineForOp> band,
593fef2d26SRiver Riddle                     SmallVectorImpl<Value> &tilingParameters) {
603fef2d26SRiver Riddle   AffineForOp topLoop = band[0];
613fef2d26SRiver Riddle   Region *funcOpRegion = topLoop->getParentRegion();
623fef2d26SRiver Riddle   unsigned nestDepth = band.size();
633fef2d26SRiver Riddle 
643fef2d26SRiver Riddle   for (BlockArgument blockArgument :
653fef2d26SRiver Riddle        funcOpRegion->getArguments().take_front(nestDepth)) {
663fef2d26SRiver Riddle     if (blockArgument.getArgNumber() < nestDepth) {
67d98e6006SVimal Patel       if (!blockArgument.getType().isIndex())
68d98e6006SVimal Patel         return topLoop->emitError(
69d98e6006SVimal Patel             "expected tiling parameters to be of index type");
703fef2d26SRiver Riddle       tilingParameters.push_back(blockArgument);
713fef2d26SRiver Riddle     }
723fef2d26SRiver Riddle   }
73d98e6006SVimal Patel   return success();
743fef2d26SRiver Riddle }
753fef2d26SRiver Riddle 
runOnOperation()7641574554SRiver Riddle void TestAffineLoopParametricTiling::runOnOperation() {
773fef2d26SRiver Riddle   // Bands of loops to tile.
783fef2d26SRiver Riddle   std::vector<SmallVector<AffineForOp, 6>> bands;
7941574554SRiver Riddle   getTileableBands(getOperation(), &bands);
803fef2d26SRiver Riddle 
813fef2d26SRiver Riddle   // Tile each band.
829cf9ed94SUday Bondhugula   for (MutableArrayRef<AffineForOp> band : bands) {
833fef2d26SRiver Riddle     // Capture the tiling parameters from the arguments to the function
843fef2d26SRiver Riddle     // enclosing this loop nest.
853fef2d26SRiver Riddle     SmallVector<AffineForOp, 6> tiledNest;
863fef2d26SRiver Riddle     SmallVector<Value, 6> tilingParameters;
873fef2d26SRiver Riddle     // Check if tiling parameters are present.
88d98e6006SVimal Patel     if (checkIfTilingParametersExist(band).failed())
89d98e6006SVimal Patel       return;
903fef2d26SRiver Riddle 
913fef2d26SRiver Riddle     // Get function arguments as tiling parameters.
92d98e6006SVimal Patel     if (getTilingParameters(band, tilingParameters).failed())
93d98e6006SVimal Patel       return;
943fef2d26SRiver Riddle 
959cf9ed94SUday Bondhugula     (void)tilePerfectlyNestedParametric(band, tilingParameters, &tiledNest);
963fef2d26SRiver Riddle   }
973fef2d26SRiver Riddle }
983fef2d26SRiver Riddle 
993fef2d26SRiver Riddle namespace mlir {
1003fef2d26SRiver Riddle namespace test {
registerTestAffineLoopParametricTilingPass()1013fef2d26SRiver Riddle void registerTestAffineLoopParametricTilingPass() {
102b5e22e6dSMehdi Amini   PassRegistration<TestAffineLoopParametricTiling>();
1033fef2d26SRiver Riddle }
1043fef2d26SRiver Riddle } // namespace test
1053fef2d26SRiver Riddle } // namespace mlir
106