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