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