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 "llvm/ADT/ArrayRef.h"
23#include "llvm/ADT/SmallPtrSet.h"
24#include <variant>
25
26namespace mlir {
27namespace omp {
28struct PrivateClauseOps;
29} // namespace omp
30} // namespace mlir
31
32namespace Fortran {
33namespace lower {
34namespace omp {
35
36class DataSharingProcessor {
37private:
41 struct OMPConstructSymbolVisitor {
42 OMPConstructSymbolVisitor(semantics::SemanticsContext &ctx)
43 : version(ctx.langOptions().OpenMPVersion) {}
44 template <typename T>
45 bool Pre(const T &) {
46 return true;
47 }
48 template <typename T>
49 void Post(const T &) {}
50
51 bool Pre(const parser::OpenMPConstruct &omp) {
52 // Skip constructs that may not have privatizations.
53 if (isOpenMPPrivatizingConstruct(omp, version))
54 constructs.push_back(&omp);
55 return true;
56 }
57
58 void Post(const parser::OpenMPConstruct &omp) {
59 if (isOpenMPPrivatizingConstruct(omp, version))
60 constructs.pop_back();
61 }
62
63 void Post(const parser::Name &name) {
64 auto current = !constructs.empty() ? constructs.back() : ConstructPtr();
65 symDefMap.try_emplace(name.symbol, current);
66 }
67
68 bool Pre(const parser::DeclarationConstruct &decl) {
69 constructs.push_back(&decl);
70 return true;
71 }
72
73 void Post(const parser::DeclarationConstruct &decl) {
74 constructs.pop_back();
75 }
76
79 bool isSymbolDefineBy(const semantics::Symbol *symbol,
80 lower::pft::Evaluation &eval) const;
81
82 // Given a \p symbol, returns true if it is defined by a nested
83 // `DeclarationConstruct`.
84 bool
85 isSymbolDefineByNestedDeclaration(const semantics::Symbol *symbol) const;
86
87 private:
88 using ConstructPtr = std::variant<const parser::OpenMPConstruct *,
91 llvm::DenseMap<semantics::Symbol *, ConstructPtr> symDefMap;
92
93 unsigned version;
94 };
95
96 mlir::OpBuilder::InsertPoint lastPrivIP;
98 // Symbols in private, firstprivate, and/or lastprivate clauses.
99 llvm::SetVector<const semantics::Symbol *> explicitlyPrivatizedSymbols;
100 llvm::SetVector<const semantics::Symbol *> defaultSymbols;
101 llvm::SetVector<const semantics::Symbol *> allPrivatizedSymbols;
102
103 lower::AbstractConverter &converter;
105 fir::FirOpBuilder &firOpBuilder;
106 omp::List<omp::Clause> clauses;
108 bool shouldCollectPreDeterminedSymbols;
109 bool useDelayedPrivatization;
110 bool forceHeapAllocationForPrivateDynamicArrays = false;
111 llvm::SmallPtrSet<const semantics::Symbol *, 16> mightHaveReadHostSym;
112 llvm::SmallPtrSet<const semantics::Symbol *, 4>
113 symbolsCoveredByReductionElements;
114 lower::SymMap &symTable;
115 bool isTargetPrivatization;
116 OMPConstructSymbolVisitor visitor;
117
118 bool needBarrier();
119 void collectPrivatizedSymbols(
120 std::optional<semantics::Symbol::Flag> flag,
121 const llvm::SetVector<const semantics::Symbol *> &allSymbols,
122 const llvm::SetVector<const semantics::Symbol *> &symbolsInNestedRegions,
123 llvm::SetVector<const semantics::Symbol *> *symbols = nullptr);
124 void
125 collectSymbols(semantics::Symbol::Flag flag,
126 llvm::SetVector<const semantics::Symbol *> *symbols = nullptr);
127 void collectSymbolsInNestedRegions(
128 lower::pft::Evaluation &eval, semantics::Symbol::Flag flag,
129 llvm::SetVector<const semantics::Symbol *> &symbolsInNestedRegions);
130 void collectOmpObjectListSymbol(
131 const omp::ObjectList &objects,
132 llvm::SetVector<const semantics::Symbol *> &symbolSet);
133 void collectSymbolsForPrivatization();
134 bool isCoveredByReductionElement(const semantics::Symbol *sym) const;
135 void insertBarrier(mlir::omp::PrivateClauseOps *clauseOps);
136 void collectDefaultSymbols();
137 void collectImplicitSymbols();
138 void collectPreDeterminedSymbols();
139 void collectIndirectReferences();
140 void privatize(mlir::omp::PrivateClauseOps *clauseOps,
141 std::optional<llvm::omp::Directive> dir = std::nullopt);
142 void copyLastPrivatize(mlir::Operation *op);
143 void insertLastPrivateCompare(mlir::Operation *op);
144 void cloneSymbol(const semantics::Symbol *sym);
145 void
146 copyFirstPrivateSymbol(const semantics::Symbol *sym,
147 mlir::OpBuilder::InsertPoint *copyAssignIP = nullptr);
148 void copyLastPrivateSymbol(const semantics::Symbol *sym,
149 mlir::OpBuilder::InsertPoint *lastPrivIP);
150 void insertDeallocs();
151
152 static bool isOpenMPPrivatizingConstruct(const parser::OpenMPConstruct &omp,
153 unsigned version);
154 bool isOpenMPPrivatizingEvaluation(const pft::Evaluation &eval) const;
155
156public:
157 DataSharingProcessor(lower::AbstractConverter &converter,
159 const List<Clause> &clauses,
161 bool shouldCollectPreDeterminedSymbols,
162 bool useDelayedPrivatization, lower::SymMap &symTable,
163 bool isTargetPrivatization = false,
165 symbolsCoveredByReductionElements = {});
166
167 DataSharingProcessor(lower::AbstractConverter &converter,
170 bool useDelayedPrivatization, lower::SymMap &symTable,
171 bool isTargetPrivatization = false,
173 symbolsCoveredByReductionElements = {});
174
175 // Privatisation is split into two steps.
176 // Step1 performs cloning of all privatisation clauses and copying for
177 // firstprivates. Step1 is performed at the place where process/processStep1
178 // is called. This is usually inside the Operation corresponding to the OpenMP
179 // construct, for looping constructs this is just before the Operation. The
180 // split into two steps was performed basically to be able to call
181 // privatisation for looping constructs before the operation is created since
182 // the bounds of the MLIR OpenMP operation can be privatised.
183 // Step2 performs the copying for lastprivates and requires knowledge of the
184 // MLIR operation to insert the last private update. Step2 adds
185 // dealocation code as well.
186 void processStep1(mlir::omp::PrivateClauseOps *clauseOps = nullptr,
187 std::optional<llvm::omp::Directive> dir = std::nullopt);
188 void processStep2(mlir::Operation *op, bool isLoop);
189
190 void pushLoopIV(mlir::Value iv) { loopIVs.push_back(iv); }
191
192 void setForceHeapAllocationForPrivateDynamicArrays(bool value = true) {
193 forceHeapAllocationForPrivateDynamicArrays = value;
194 }
195
196 const llvm::SetVector<const semantics::Symbol *> &
197 getAllSymbolsToPrivatize() const {
198 return allPrivatizedSymbols;
199 }
200
201 llvm::ArrayRef<const semantics::Symbol *> getDelayedPrivSymbols() const {
202 return useDelayedPrivatization
203 ? allPrivatizedSymbols.getArrayRef()
205 }
206
207 void privatizeSymbol(const semantics::Symbol *symToPrivatize,
208 mlir::omp::PrivateClauseOps *clauseOps,
209 std::optional<llvm::omp::Directive> dir = std::nullopt);
210};
211
212} // namespace omp
213} // namespace lower
214} // namespace Fortran
215
216#endif // FORTRAN_LOWER_DATASHARINGPROCESSOR_H
Definition AbstractConverter.h:87
Definition SymbolMap.h:181
Definition semantics.h:67
Definition symbol.h:884
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:5549