1 //= TestAffineLoopParametricTiling.cpp -- Parametric Affine loop tiling pass =// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements a test pass to test parametric tiling of perfectly 10 // nested affine for loops. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "mlir/Dialect/Affine/IR/AffineOps.h" 15 #include "mlir/Dialect/Affine/Passes.h" 16 #include "mlir/Transforms/LoopUtils.h" 17 18 using namespace mlir; 19 20 #define DEBUG_TYPE "test-affine-parametric-tile" 21 22 namespace { 23 struct TestAffineLoopParametricTiling 24 : public PassWrapper<TestAffineLoopParametricTiling, FunctionPass> { 25 void runOnFunction() override; 26 }; 27 } // end anonymous namespace 28 29 /// Checks if the function enclosing the loop nest has any arguments passed to 30 /// it, which can be used as tiling parameters. Assumes that atleast 'n' 31 /// arguments are passed, where 'n' is the number of loops in the loop nest. 32 static void checkIfTilingParametersExist(ArrayRef<AffineForOp> band) { 33 assert(!band.empty() && "no loops in input band"); 34 AffineForOp topLoop = band[0]; 35 36 if (FuncOp funcOp = dyn_cast<FuncOp>(topLoop->getParentOp())) 37 assert(funcOp.getNumArguments() >= band.size() && "Too few tile sizes"); 38 } 39 40 /// Captures tiling parameters, which are expected to be passed as arguments 41 /// to the function enclosing the loop nest. Also checks if the required 42 /// parameters are of index type. This approach is temporary for testing 43 /// purposes. 44 static void getTilingParameters(ArrayRef<AffineForOp> band, 45 SmallVectorImpl<Value> &tilingParameters) { 46 AffineForOp topLoop = band[0]; 47 Region *funcOpRegion = topLoop->getParentRegion(); 48 unsigned nestDepth = band.size(); 49 50 for (BlockArgument blockArgument : 51 funcOpRegion->getArguments().take_front(nestDepth)) { 52 if (blockArgument.getArgNumber() < nestDepth) { 53 assert(blockArgument.getType().isIndex() && 54 "expected tiling parameters to be of index type."); 55 tilingParameters.push_back(blockArgument); 56 } 57 } 58 } 59 60 void TestAffineLoopParametricTiling::runOnFunction() { 61 // Bands of loops to tile. 62 std::vector<SmallVector<AffineForOp, 6>> bands; 63 getTileableBands(getFunction(), &bands); 64 65 // Tile each band. 66 for (SmallVectorImpl<AffineForOp> &band : bands) { 67 // Capture the tiling parameters from the arguments to the function 68 // enclosing this loop nest. 69 SmallVector<AffineForOp, 6> tiledNest; 70 SmallVector<Value, 6> tilingParameters; 71 // Check if tiling parameters are present. 72 checkIfTilingParametersExist(band); 73 74 // Get function arguments as tiling parameters. 75 getTilingParameters(band, tilingParameters); 76 77 if (failed( 78 tilePerfectlyNestedParametric(band, tilingParameters, &tiledNest))) 79 return signalPassFailure(); 80 } 81 } 82 83 namespace mlir { 84 namespace test { 85 void registerTestAffineLoopParametricTilingPass() { 86 PassRegistration<TestAffineLoopParametricTiling>( 87 "test-affine-parametric-tile", 88 "Tile affine loops using SSA values as tile sizes"); 89 } 90 } // namespace test 91 } // namespace mlir 92