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
23namespace mlir {
24namespace omp {
25struct PrivateClauseOps;
26} // namespace omp
27} // namespace mlir
28
29namespace Fortran {
30namespace lower {
31namespace omp {
32
33class DataSharingProcessor {
34private:
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 (isOpenMPPrivatizingConstruct(omp))
49 constructs.push_back(&omp);
50 return true;
51 }
52
53 void Post(const parser::OpenMPConstruct &omp) {
54 if (isOpenMPPrivatizingConstruct(omp))
55 constructs.pop_back();
56 }
57
58 void Post(const parser::Name &name) {
59 auto *current = !constructs.empty() ? constructs.back() : nullptr;
60 symDefMap.try_emplace(name.symbol, current);
61 }
62
63 llvm::SmallVector<const parser::OpenMPConstruct *> constructs;
64 llvm::DenseMap<semantics::Symbol *, const parser::OpenMPConstruct *>
65 symDefMap;
66
67 /// Given a \p symbol and an \p eval, returns true if eval is the OMP
68 /// construct that defines symbol.
69 bool isSymbolDefineBy(const semantics::Symbol *symbol,
70 lower::pft::Evaluation &eval) const;
71 };
72
73 mlir::OpBuilder::InsertPoint lastPrivIP;
74 llvm::SmallVector<mlir::Value> loopIVs;
75 // Symbols in private, firstprivate, and/or lastprivate clauses.
76 llvm::SetVector<const semantics::Symbol *> explicitlyPrivatizedSymbols;
77 llvm::SetVector<const semantics::Symbol *> defaultSymbols;
78 llvm::SetVector<const semantics::Symbol *> implicitSymbols;
79 llvm::SetVector<const semantics::Symbol *> preDeterminedSymbols;
80 llvm::SetVector<const semantics::Symbol *> allPrivatizedSymbols;
81
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 llvm::SmallSet<const semantics::Symbol *, 16> mightHaveReadHostSym;
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(mlir::omp::PrivateClauseOps *clauseOps);
104 void collectDefaultSymbols();
105 void collectImplicitSymbols();
106 void collectPreDeterminedSymbols();
107 void privatize(mlir::omp::PrivateClauseOps *clauseOps);
108 void copyLastPrivatize(mlir::Operation *op);
109 void insertLastPrivateCompare(mlir::Operation *op);
110 void cloneSymbol(const semantics::Symbol *sym);
111 void
112 copyFirstPrivateSymbol(const semantics::Symbol *sym,
113 mlir::OpBuilder::InsertPoint *copyAssignIP = nullptr);
114 void copyLastPrivateSymbol(const semantics::Symbol *sym,
115 mlir::OpBuilder::InsertPoint *lastPrivIP);
116 void insertDeallocs();
117
118 static bool isOpenMPPrivatizingConstruct(const parser::OpenMPConstruct &omp);
119 bool isOpenMPPrivatizingEvaluation(const pft::Evaluation &eval) const;
120
121public:
122 DataSharingProcessor(lower::AbstractConverter &converter,
123 semantics::SemanticsContext &semaCtx,
124 const List<Clause> &clauses,
125 lower::pft::Evaluation &eval,
126 bool shouldCollectPreDeterminedSymbols,
127 bool useDelayedPrivatization, lower::SymMap &symTable);
128
129 DataSharingProcessor(lower::AbstractConverter &converter,
130 semantics::SemanticsContext &semaCtx,
131 lower::pft::Evaluation &eval,
132 bool useDelayedPrivatization, lower::SymMap &symTable);
133
134 // Privatisation is split into two steps.
135 // Step1 performs cloning of all privatisation clauses and copying for
136 // firstprivates. Step1 is performed at the place where process/processStep1
137 // is called. This is usually inside the Operation corresponding to the OpenMP
138 // construct, for looping constructs this is just before the Operation. The
139 // split into two steps was performed basically to be able to call
140 // privatisation for looping constructs before the operation is created since
141 // the bounds of the MLIR OpenMP operation can be privatised.
142 // Step2 performs the copying for lastprivates and requires knowledge of the
143 // MLIR operation to insert the last private update. Step2 adds
144 // dealocation code as well.
145 void processStep1(mlir::omp::PrivateClauseOps *clauseOps = nullptr);
146 void processStep2(mlir::Operation *op, bool isLoop);
147
148 void pushLoopIV(mlir::Value iv) { loopIVs.push_back(iv); }
149
150 const llvm::SetVector<const semantics::Symbol *> &
151 getAllSymbolsToPrivatize() const {
152 return allPrivatizedSymbols;
153 }
154
155 llvm::ArrayRef<const semantics::Symbol *> getDelayedPrivSymbols() const {
156 return useDelayedPrivatization
157 ? allPrivatizedSymbols.getArrayRef()
158 : llvm::ArrayRef<const semantics::Symbol *>();
159 }
160
161 void privatizeSymbol(const semantics::Symbol *symToPrivatize,
162 mlir::omp::PrivateClauseOps *clauseOps);
163};
164
165} // namespace omp
166} // namespace lower
167} // namespace Fortran
168
169#endif // FORTRAN_LOWER_DATASHARINGPROCESSOR_H
170

source code of flang/lib/Lower/OpenMP/DataSharingProcessor.h