1 //===- AffineParallelize.cpp - Affineparallelize 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 parallelizer for affine loop nests that is able to 10 // perform inner or outer loop parallelization. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "PassDetail.h" 15 #include "mlir/Analysis/AffineStructures.h" 16 #include "mlir/Analysis/LoopAnalysis.h" 17 #include "mlir/Analysis/Utils.h" 18 #include "mlir/Dialect/Affine/IR/AffineOps.h" 19 #include "mlir/Dialect/Affine/IR/AffineValueMap.h" 20 #include "mlir/Dialect/Affine/Passes.h" 21 #include "mlir/Dialect/Affine/Passes.h.inc" 22 #include "mlir/Dialect/Affine/Utils.h" 23 #include "mlir/Transforms/LoopUtils.h" 24 #include "llvm/Support/Debug.h" 25 26 #define DEBUG_TYPE "affine-parallel" 27 28 using namespace mlir; 29 30 namespace { 31 /// Convert all parallel affine.for op into 1-D affine.parallel op. 32 struct AffineParallelize : public AffineParallelizeBase<AffineParallelize> { 33 void runOnFunction() override; 34 }; 35 } // namespace 36 runOnFunction()37void AffineParallelize::runOnFunction() { 38 FuncOp f = getFunction(); 39 40 // The walker proceeds in post-order, but we need to process outer loops first 41 // to control the number of outer parallel loops, so push candidate loops to 42 // the front of a deque. 43 std::deque<AffineForOp> parallelizableLoops; 44 f.walk([&](AffineForOp loop) { 45 if (isLoopParallel(loop)) 46 parallelizableLoops.push_front(loop); 47 }); 48 49 for (AffineForOp loop : parallelizableLoops) { 50 unsigned numParentParallelOps = 0; 51 for (Operation *op = loop->getParentOp(); 52 op != nullptr && !op->hasTrait<OpTrait::AffineScope>(); 53 op = op->getParentOp()) { 54 if (isa<AffineParallelOp>(op)) 55 ++numParentParallelOps; 56 } 57 58 if (numParentParallelOps < maxNested) 59 affineParallelize(loop); 60 } 61 } 62 createAffineParallelizePass()63std::unique_ptr<OperationPass<FuncOp>> mlir::createAffineParallelizePass() { 64 return std::make_unique<AffineParallelize>(); 65 } 66