1 //===-- Lower/OpenMP/DataSharingProcessor.h ---------------------*- C++ -*-===// 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 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ 10 // 11 //===----------------------------------------------------------------------===// 12 #ifndef FORTRAN_LOWER_DATASHARINGPROCESSOR_H 13 #define FORTRAN_LOWER_DATASHARINGPROCESSOR_H 14 15 #include "Clauses.h" 16 #include "flang/Lower/AbstractConverter.h" 17 #include "flang/Lower/OpenMP.h" 18 #include "flang/Optimizer/Builder/FIRBuilder.h" 19 #include "flang/Parser/parse-tree.h" 20 #include "flang/Semantics/symbol.h" 21 #include "mlir/Dialect/OpenMP/OpenMPDialect.h" 22 23 namespace mlir { 24 namespace omp { 25 struct PrivateClauseOps; 26 } // namespace omp 27 } // namespace mlir 28 29 namespace Fortran { 30 namespace lower { 31 namespace omp { 32 33 class DataSharingProcessor { 34 private: 35 /// A symbol visitor that keeps track of the currently active OpenMPConstruct 36 /// at any point in time. This is used to track Symbol definition scopes in 37 /// order to tell which OMP scope defined vs. references a certain Symbol. 38 struct OMPConstructSymbolVisitor { 39 template <typename T> 40 bool Pre(const T &) { 41 return true; 42 } 43 template <typename T> 44 void Post(const T &) {} 45 46 bool Pre(const parser::OpenMPConstruct &omp) { 47 // Skip constructs that may not have privatizations. 48 if (!std::holds_alternative<parser::OpenMPCriticalConstruct>(omp.u)) 49 currentConstruct = &omp; 50 return true; 51 } 52 53 void Post(const parser::OpenMPConstruct &omp) { 54 currentConstruct = nullptr; 55 } 56 57 void Post(const parser::Name &name) { 58 symDefMap.try_emplace(name.symbol, currentConstruct); 59 } 60 61 const parser::OpenMPConstruct *currentConstruct = nullptr; 62 llvm::DenseMap<semantics::Symbol *, const parser::OpenMPConstruct *> 63 symDefMap; 64 65 /// Given a \p symbol and an \p eval, returns true if eval is the OMP 66 /// construct that defines symbol. 67 bool isSymbolDefineBy(const semantics::Symbol *symbol, 68 lower::pft::Evaluation &eval) const; 69 }; 70 71 mlir::OpBuilder::InsertPoint lastPrivIP; 72 llvm::SmallVector<mlir::Value> loopIVs; 73 // Symbols in private, firstprivate, and/or lastprivate clauses. 74 llvm::SetVector<const semantics::Symbol *> explicitlyPrivatizedSymbols; 75 llvm::SetVector<const semantics::Symbol *> defaultSymbols; 76 llvm::SetVector<const semantics::Symbol *> implicitSymbols; 77 llvm::SetVector<const semantics::Symbol *> preDeterminedSymbols; 78 llvm::SetVector<const semantics::Symbol *> allPrivatizedSymbols; 79 80 llvm::DenseMap<const semantics::Symbol *, mlir::omp::PrivateClauseOp> 81 symToPrivatizer; 82 lower::AbstractConverter &converter; 83 semantics::SemanticsContext &semaCtx; 84 fir::FirOpBuilder &firOpBuilder; 85 omp::List<omp::Clause> clauses; 86 lower::pft::Evaluation &eval; 87 bool shouldCollectPreDeterminedSymbols; 88 bool useDelayedPrivatization; 89 bool callsInitClone = false; 90 lower::SymMap &symTable; 91 OMPConstructSymbolVisitor visitor; 92 93 bool needBarrier(); 94 void collectSymbols(semantics::Symbol::Flag flag, 95 llvm::SetVector<const semantics::Symbol *> &symbols); 96 void collectSymbolsInNestedRegions( 97 lower::pft::Evaluation &eval, semantics::Symbol::Flag flag, 98 llvm::SetVector<const semantics::Symbol *> &symbolsInNestedRegions); 99 void collectOmpObjectListSymbol( 100 const omp::ObjectList &objects, 101 llvm::SetVector<const semantics::Symbol *> &symbolSet); 102 void collectSymbolsForPrivatization(); 103 void insertBarrier(); 104 void collectDefaultSymbols(); 105 void collectImplicitSymbols(); 106 void collectPreDeterminedSymbols(); 107 void privatize(mlir::omp::PrivateClauseOps *clauseOps); 108 void doPrivatize(const semantics::Symbol *sym, 109 mlir::omp::PrivateClauseOps *clauseOps); 110 void copyLastPrivatize(mlir::Operation *op); 111 void insertLastPrivateCompare(mlir::Operation *op); 112 void cloneSymbol(const semantics::Symbol *sym); 113 void 114 copyFirstPrivateSymbol(const semantics::Symbol *sym, 115 mlir::OpBuilder::InsertPoint *copyAssignIP = nullptr); 116 void copyLastPrivateSymbol(const semantics::Symbol *sym, 117 mlir::OpBuilder::InsertPoint *lastPrivIP); 118 void insertDeallocs(); 119 120 public: 121 DataSharingProcessor(lower::AbstractConverter &converter, 122 semantics::SemanticsContext &semaCtx, 123 const List<Clause> &clauses, 124 lower::pft::Evaluation &eval, 125 bool shouldCollectPreDeterminedSymbols, 126 bool useDelayedPrivatization, lower::SymMap &symTable); 127 128 // Privatisation is split into two steps. 129 // Step1 performs cloning of all privatisation clauses and copying for 130 // firstprivates. Step1 is performed at the place where process/processStep1 131 // is called. This is usually inside the Operation corresponding to the OpenMP 132 // construct, for looping constructs this is just before the Operation. The 133 // split into two steps was performed basically to be able to call 134 // privatisation for looping constructs before the operation is created since 135 // the bounds of the MLIR OpenMP operation can be privatised. 136 // Step2 performs the copying for lastprivates and requires knowledge of the 137 // MLIR operation to insert the last private update. Step2 adds 138 // dealocation code as well. 139 void processStep1(mlir::omp::PrivateClauseOps *clauseOps = nullptr); 140 void processStep2(mlir::Operation *op, bool isLoop); 141 142 void pushLoopIV(mlir::Value iv) { loopIVs.push_back(iv); } 143 144 const llvm::SetVector<const semantics::Symbol *> & 145 getAllSymbolsToPrivatize() const { 146 return allPrivatizedSymbols; 147 } 148 149 llvm::ArrayRef<const semantics::Symbol *> getDelayedPrivSymbols() const { 150 return useDelayedPrivatization 151 ? allPrivatizedSymbols.getArrayRef() 152 : llvm::ArrayRef<const semantics::Symbol *>(); 153 } 154 }; 155 156 } // namespace omp 157 } // namespace lower 158 } // namespace Fortran 159 160 #endif // FORTRAN_LOWER_DATASHARINGPROCESSOR_H 161