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 #include <deque> 26 27 #define DEBUG_TYPE "affine-parallel" 28 29 using namespace mlir; 30 31 namespace { 32 /// Convert all parallel affine.for op into 1-D affine.parallel op. 33 struct AffineParallelize : public AffineParallelizeBase<AffineParallelize> { 34 void runOnFunction() override; 35 }; 36 } // namespace 37 38 void AffineParallelize::runOnFunction() { 39 FuncOp f = getFunction(); 40 41 // The walker proceeds in post-order, but we need to process outer loops first 42 // to control the number of outer parallel loops, so push candidate loops to 43 // the front of a deque. 44 std::deque<AffineForOp> parallelizableLoops; 45 f.walk([&](AffineForOp loop) { 46 if (isLoopParallel(loop)) 47 parallelizableLoops.push_front(loop); 48 }); 49 50 for (AffineForOp loop : parallelizableLoops) { 51 unsigned numParentParallelOps = 0; 52 for (Operation *op = loop->getParentOp(); 53 op != nullptr && !op->hasTrait<OpTrait::AffineScope>(); 54 op = op->getParentOp()) { 55 if (isa<AffineParallelOp>(op)) 56 ++numParentParallelOps; 57 } 58 59 if (numParentParallelOps < maxNested) 60 affineParallelize(loop); 61 } 62 } 63 64 std::unique_ptr<OperationPass<FuncOp>> mlir::createAffineParallelizePass() { 65 return std::make_unique<AffineParallelize>(); 66 } 67