FLANG
DataSharingProcessor.h
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 "flang/Lower/AbstractConverter.h"
16#include "flang/Lower/OpenMP.h"
17#include "flang/Lower/OpenMP/Clauses.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#include <variant>
23
24namespace mlir {
25namespace omp {
26struct PrivateClauseOps;
27} // namespace omp
28} // namespace mlir
29
30namespace Fortran {
31namespace lower {
32namespace omp {
33
34class DataSharingProcessor {
35private:
39 struct OMPConstructSymbolVisitor {
40 OMPConstructSymbolVisitor(
43 : metadirectiveLoopIVs(metadirectiveLoopIVs.begin(),
44 metadirectiveLoopIVs.end()),
45 isMetadirectiveLoop(!metadirectiveLoopIVs.empty()),
46 version(ctx.langOptions().getOpenMPVersion()) {}
47 template <typename T>
48 bool Pre(const T &) {
49 return true;
50 }
51 template <typename T>
52 void Post(const T &) {}
53
54 bool Pre(const parser::LoopControl::Bounds &bounds) {
55 if (isMetadirectiveLoop)
56 if (const semantics::Symbol *symbol = bounds.Name().thing.symbol)
57 metadirectiveLoopIVs.insert(symbol);
58 return true;
59 }
60
61 bool Pre(const parser::OpenMPConstruct &omp) {
62 // Skip constructs that may not have privatizations.
63 if (isOpenMPPrivatizingConstruct(omp, version))
64 constructs.push_back(&omp);
65 return true;
66 }
67
68 void Post(const parser::OpenMPConstruct &omp) {
69 if (isOpenMPPrivatizingConstruct(omp, version))
70 constructs.pop_back();
71 }
72
73 void Post(const parser::Name &name) {
74 auto current = !constructs.empty() ? constructs.back() : ConstructPtr();
75 symDefMap.try_emplace(name.symbol, current);
76 }
77
78 bool Pre(const parser::DeclarationConstruct &decl) {
79 constructs.push_back(&decl);
80 return true;
81 }
82
83 void Post(const parser::DeclarationConstruct &decl) {
84 constructs.pop_back();
85 }
86
89 bool isSymbolDefineBy(const semantics::Symbol *symbol,
90 lower::pft::Evaluation &eval) const;
91
92 // Given a \p symbol, returns true if it is defined by a nested
93 // `DeclarationConstruct`.
94 bool
95 isSymbolDefineByNestedDeclaration(const semantics::Symbol *symbol) const;
96
97 private:
98 using ConstructPtr = std::variant<const parser::OpenMPConstruct *,
101 llvm::DenseMap<semantics::Symbol *, ConstructPtr> symDefMap;
102 llvm::SmallPtrSet<const semantics::Symbol *, 4> metadirectiveLoopIVs;
103 bool isMetadirectiveLoop;
104
105 llvm::omp::Version version;
106 };
107
108 mlir::OpBuilder::InsertPoint lastPrivIP;
110 // Symbols in private, firstprivate, and/or lastprivate clauses.
111 llvm::SetVector<const semantics::Symbol *> explicitlyPrivatizedSymbols;
112 llvm::SetVector<const semantics::Symbol *> defaultSymbols;
113 llvm::SetVector<const semantics::Symbol *> allPrivatizedSymbols;
114 llvm::SetVector<const semantics::Symbol *> conditionalLastPrivatizedSymbols;
115 // When true, conditional-lastprivate list items get an ordinary private copy
116 // (their in-loop working value) plus a separate reduction struct as the
117 // conditional-last accumulator. Used by worksharing loops, where a
118 // nonmonotonic schedule can execute chunks out of order. When false the list
119 // item is bound directly to the reduction struct (used by sections, which are
120 // lexically ordered and never need the private copy).
121 bool conditionalLpUsesPrivateCopy = false;
122
123 lower::AbstractConverter &converter;
125 fir::FirOpBuilder &firOpBuilder;
126 omp::List<omp::Clause> clauses;
128 bool shouldCollectPreDeterminedSymbols;
129 bool useDelayedPrivatization;
130 bool forceHeapAllocationForPrivateDynamicArrays = false;
131 llvm::SmallPtrSet<const semantics::Symbol *, 16> mightHaveReadHostSym;
132 lower::SymMap &symTable;
133 bool isTargetPrivatization;
134 bool isMetadirectiveLoop;
135 OMPConstructSymbolVisitor visitor;
136
137 bool needBarrier();
138 void collectPrivatizedSymbols(
139 std::optional<semantics::Symbol::Flag> flag,
140 const llvm::SetVector<const semantics::Symbol *> &allSymbols,
141 const llvm::SetVector<const semantics::Symbol *> &symbolsInNestedRegions,
142 llvm::SetVector<const semantics::Symbol *> *symbols = nullptr);
143 void
144 collectSymbols(semantics::Symbol::Flag flag,
145 llvm::SetVector<const semantics::Symbol *> *symbols = nullptr);
146 void collectSymbolsInNestedRegions(
147 lower::pft::Evaluation &eval, semantics::Symbol::Flag flag,
148 llvm::SetVector<const semantics::Symbol *> &symbolsInNestedRegions);
149 void collectOmpObjectListSymbol(
150 const omp::ObjectList &objects,
151 llvm::SetVector<const semantics::Symbol *> &symbolSet);
152 void collectSymbolsForPrivatization();
153 void insertBarrier(mlir::omp::PrivateClauseOps *clauseOps);
154 void collectDefaultSymbols();
155 void collectImplicitSymbols();
156 void collectPreDeterminedSymbols();
157 void collectIndirectReferences();
158 void privatize(mlir::omp::PrivateClauseOps *clauseOps,
159 std::optional<llvm::omp::Directive> dir = std::nullopt);
160 void copyLastPrivatize(mlir::Operation *op);
161 void insertLastPrivateCompare(mlir::Operation *op);
162 void cloneSymbol(const semantics::Symbol *sym);
163 void
164 copyFirstPrivateSymbol(const semantics::Symbol *sym,
165 mlir::OpBuilder::InsertPoint *copyAssignIP = nullptr);
166 void copyLastPrivateSymbol(const semantics::Symbol *sym,
167 mlir::OpBuilder::InsertPoint *lastPrivIP);
168 void insertDeallocs();
169
170 static bool isOpenMPPrivatizingConstruct(const parser::OpenMPConstruct &omp,
171 llvm::omp::Version version);
172 bool isOpenMPPrivatizingEvaluation(const pft::Evaluation &eval) const;
173
174public:
175 DataSharingProcessor(
177 const List<Clause> &clauses, lower::pft::Evaluation &eval,
178 bool shouldCollectPreDeterminedSymbols, bool useDelayedPrivatization,
179 lower::SymMap &symTable, bool isTargetPrivatization = false,
180 llvm::ArrayRef<const semantics::Symbol *> metadirectiveLoopIVs = {});
181
182 DataSharingProcessor(lower::AbstractConverter &converter,
185 bool useDelayedPrivatization, lower::SymMap &symTable,
186 bool isTargetPrivatization = false);
187
188 // Privatisation is split into two steps.
189 // Step1 performs cloning of all privatisation clauses and copying for
190 // firstprivates. Step1 is performed at the place where process/processStep1
191 // is called. This is usually inside the Operation corresponding to the OpenMP
192 // construct, for looping constructs this is just before the Operation. The
193 // split into two steps was performed basically to be able to call
194 // privatisation for looping constructs before the operation is created since
195 // the bounds of the MLIR OpenMP operation can be privatised.
196 // Step2 performs the copying for lastprivates and requires knowledge of the
197 // MLIR operation to insert the last private update. Step2 adds
198 // dealocation code as well.
199 void processStep1(mlir::omp::PrivateClauseOps *clauseOps = nullptr,
200 std::optional<llvm::omp::Directive> dir = std::nullopt);
201 void processStep2(mlir::Operation *op, bool isLoop);
202
203 void pushLoopIV(mlir::Value iv) { loopIVs.push_back(iv); }
204
205 void setForceHeapAllocationForPrivateDynamicArrays(bool value = true) {
206 forceHeapAllocationForPrivateDynamicArrays = value;
207 }
208
209 const llvm::SetVector<const semantics::Symbol *> &
210 getAllSymbolsToPrivatize() const {
211 return allPrivatizedSymbols;
212 }
213
214 llvm::ArrayRef<const semantics::Symbol *> getDelayedPrivSymbols() const {
215 return useDelayedPrivatization
216 ? allPrivatizedSymbols.getArrayRef()
218 }
219
220 void privatizeSymbol(const semantics::Symbol *symToPrivatize,
221 mlir::omp::PrivateClauseOps *clauseOps,
222 std::optional<llvm::omp::Directive> dir = std::nullopt);
223
224 const llvm::SetVector<const semantics::Symbol *> &
225 getConditionalLastprivateSymbols() const {
226 return conditionalLastPrivatizedSymbols;
227 }
228
229 void setConditionalLpUsesPrivateCopy(bool v) {
230 conditionalLpUsesPrivateCopy = v;
231 }
232};
233
234} // namespace omp
235} // namespace lower
236} // namespace Fortran
237
238#endif // FORTRAN_LOWER_DATASHARINGPROCESSOR_H
Definition AbstractConverter.h:87
Definition SymbolMap.h:181
Definition semantics.h:67
Definition symbol.h:910
Definition FIRBuilder.h:66
Definition FIRType.h:106
Definition OpenACC.h:20
Definition ParserActions.h:24
Definition bit-population-count.h:20
Definition AbstractConverter.h:32
Definition PFTBuilder.h:221
Definition parse-tree.h:442
Definition parse-tree.h:592
Definition parse-tree.h:5670