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 StringRef getArgument() const final { return "test-affine-parametric-tile"; } 26 StringRef getDescription() const final { 27 return "Tile affine loops using SSA values as tile sizes"; 28 } 29 void runOnFunction() override; 30 }; 31 } // end anonymous namespace 32 33 /// Checks if the function enclosing the loop nest has any arguments passed to 34 /// it, which can be used as tiling parameters. Assumes that atleast 'n' 35 /// arguments are passed, where 'n' is the number of loops in the loop nest. 36 static void checkIfTilingParametersExist(ArrayRef<AffineForOp> band) { 37 assert(!band.empty() && "no loops in input band"); 38 AffineForOp topLoop = band[0]; 39 40 if (FuncOp funcOp = dyn_cast<FuncOp>(topLoop->getParentOp())) 41 assert(funcOp.getNumArguments() >= band.size() && "Too few tile sizes"); 42 } 43 44 /// Captures tiling parameters, which are expected to be passed as arguments 45 /// to the function enclosing the loop nest. Also checks if the required 46 /// parameters are of index type. This approach is temporary for testing 47 /// purposes. 48 static void getTilingParameters(ArrayRef<AffineForOp> band, 49 SmallVectorImpl<Value> &tilingParameters) { 50 AffineForOp topLoop = band[0]; 51 Region *funcOpRegion = topLoop->getParentRegion(); 52 unsigned nestDepth = band.size(); 53 54 for (BlockArgument blockArgument : 55 funcOpRegion->getArguments().take_front(nestDepth)) { 56 if (blockArgument.getArgNumber() < nestDepth) { 57 assert(blockArgument.getType().isIndex() && 58 "expected tiling parameters to be of index type."); 59 tilingParameters.push_back(blockArgument); 60 } 61 } 62 } 63 64 void TestAffineLoopParametricTiling::runOnFunction() { 65 // Bands of loops to tile. 66 std::vector<SmallVector<AffineForOp, 6>> bands; 67 getTileableBands(getFunction(), &bands); 68 69 // Tile each band. 70 for (SmallVectorImpl<AffineForOp> &band : bands) { 71 // Capture the tiling parameters from the arguments to the function 72 // enclosing this loop nest. 73 SmallVector<AffineForOp, 6> tiledNest; 74 SmallVector<Value, 6> tilingParameters; 75 // Check if tiling parameters are present. 76 checkIfTilingParametersExist(band); 77 78 // Get function arguments as tiling parameters. 79 getTilingParameters(band, tilingParameters); 80 81 if (failed( 82 tilePerfectlyNestedParametric(band, tilingParameters, &tiledNest))) 83 return signalPassFailure(); 84 } 85 } 86 87 namespace mlir { 88 namespace test { 89 void registerTestAffineLoopParametricTilingPass() { 90 PassRegistration<TestAffineLoopParametricTiling>(); 91 } 92 } // namespace test 93 } // namespace mlir 94