@@ -143,15 +143,17 @@ static void genNestedEvaluations(Fortran::lower::AbstractConverter &converter,
143143// ===----------------------------------------------------------------------===//
144144
145145class DataSharingProcessor {
146+ using SymbolSet = llvm::SetVector<const Fortran::semantics::Symbol *>;
147+
146148 bool hasLastPrivateOp;
147149 mlir::OpBuilder::InsertPoint lastPrivIP;
148150 mlir::OpBuilder::InsertPoint insPt;
149151 mlir::Value loopIV;
150152 // Symbols in private, firstprivate, and/or lastprivate clauses.
151- llvm::SetVector< const Fortran::semantics::Symbol *> privatizedSymbols;
152- llvm::SetVector< const Fortran::semantics::Symbol *> defaultSymbols;
153- llvm::SetVector< const Fortran::semantics::Symbol *> symbolsInNestedRegions;
154- llvm::SetVector< const Fortran::semantics::Symbol *> symbolsInParentRegions;
153+ SymbolSet privatizedSymbols;
154+ SymbolSet defaultSymbols;
155+ SymbolSet symbolsInNestedRegions;
156+ SymbolSet symbolsInParentRegions;
155157 Fortran::lower::AbstractConverter &converter;
156158 fir::FirOpBuilder &firOpBuilder;
157159 const Fortran::parser::OmpClauseList &opClauseList;
@@ -182,35 +184,54 @@ class DataSharingProcessor {
182184 : hasLastPrivateOp(false ), converter(converter),
183185 firOpBuilder (converter.getFirOpBuilder()), opClauseList(opClauseList),
184186 eval(eval) {}
185- // Privatisation is split into two steps.
186- // Step1 performs cloning of all privatisation clauses and copying for
187- // firstprivates. Step1 is performed at the place where process/processStep1
187+ // Privatisation is split into 3 steps:
188+ //
189+ // * Step1: collects all symbols that should be privatized.
190+ //
191+ // * Step2: performs cloning of all privatisation clauses and copying for
192+ // firstprivates. Step2 is performed at the place where process/processStep2
188193 // is called. This is usually inside the Operation corresponding to the OpenMP
189- // construct, for looping constructs this is just before the Operation. The
190- // split into two steps was performed basically to be able to call
191- // privatisation for looping constructs before the operation is created since
192- // the bounds of the MLIR OpenMP operation can be privatised.
193- // Step2 performs the copying for lastprivates and requires knowledge of the
194- // MLIR operation to insert the last private update. Step2 adds
194+ // construct, for looping constructs this is just before the Operation.
195+ //
196+ // * Step3: performs the copying for lastprivates and requires knowledge of
197+ // the MLIR operation to insert the last private update. Step2 adds
195198 // dealocation code as well.
199+ //
200+ // The split was performed for the following reasons:
201+ //
202+ // 1. Step1 was split so that the `target` op knows which symbols should not
203+ // be mapped into the target region due to being `private`. The implicit
204+ // mapping happens before the op body is generated so we need to to collect
205+ // the private symbols first and then later in the body actually privatize
206+ // them.
207+ //
208+ // 2. Step2 was split in order to call privatisation for looping constructs
209+ // before the operation is created since the bounds of the MLIR OpenMP
210+ // operation can be privatised.
196211 void processStep1 ();
197- void processStep2 (mlir::Operation *op, bool isLoop);
212+ void processStep2 ();
213+ void processStep3 (mlir::Operation *op, bool isLoop);
198214
199215 void setLoopIV (mlir::Value iv) {
200216 assert (!loopIV && " Loop iteration variable already set" );
201217 loopIV = iv;
202218 }
219+
220+ const SymbolSet &getPrivatizedSymbols () const { return privatizedSymbols; }
203221};
204222
205223void DataSharingProcessor::processStep1 () {
206224 collectSymbolsForPrivatization ();
207225 collectDefaultSymbols ();
226+ }
227+
228+ void DataSharingProcessor::processStep2 () {
208229 privatize ();
209230 defaultPrivatize ();
210231 insertBarrier ();
211232}
212233
213- void DataSharingProcessor::processStep2 (mlir::Operation *op, bool isLoop) {
234+ void DataSharingProcessor::processStep3 (mlir::Operation *op, bool isLoop) {
214235 insPt = firOpBuilder.saveInsertionPoint ();
215236 copyLastPrivatize (op);
216237 firOpBuilder.restoreInsertionPoint (insPt);
@@ -2306,11 +2327,12 @@ static void createBodyOfOp(
23062327 if (!dsp) {
23072328 DataSharingProcessor proc (converter, *clauses, eval);
23082329 proc.processStep1 ();
2309- proc.processStep2 (op, isLoop);
2330+ proc.processStep2 ();
2331+ proc.processStep3 (op, isLoop);
23102332 } else {
23112333 if (isLoop && args.size () > 0 )
23122334 dsp->setLoopIV (converter.getSymbolAddress (*args[0 ]));
2313- dsp->processStep2 (op, isLoop);
2335+ dsp->processStep3 (op, isLoop);
23142336 }
23152337
23162338 if (storeOp)
@@ -2648,7 +2670,9 @@ static void genBodyOfTargetOp(
26482670 const llvm::SmallVector<mlir::Type> &mapSymTypes,
26492671 const llvm::SmallVector<mlir::Location> &mapSymLocs,
26502672 const llvm::SmallVector<const Fortran::semantics::Symbol *> &mapSymbols,
2651- const mlir::Location ¤tLocation) {
2673+ const mlir::Location ¤tLocation,
2674+ const Fortran::parser::OmpClauseList &clauseList,
2675+ DataSharingProcessor &dsp) {
26522676 assert (mapSymTypes.size () == mapSymLocs.size ());
26532677
26542678 fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
@@ -2657,6 +2681,8 @@ static void genBodyOfTargetOp(
26572681 auto *regionBlock =
26582682 firOpBuilder.createBlock (®ion, {}, mapSymTypes, mapSymLocs);
26592683
2684+ dsp.processStep2 ();
2685+
26602686 // Clones the `bounds` placing them inside the target region and returns them.
26612687 auto cloneBound = [&](mlir::Value bound) {
26622688 if (mlir::isMemoryEffectFree (bound.getDefiningOp ())) {
@@ -2811,8 +2837,7 @@ genTargetOp(Fortran::lower::AbstractConverter &converter,
28112837 cp.processNowait (nowaitAttr);
28122838 cp.processMap (currentLocation, directive, semanticsContext, stmtCtx,
28132839 mapOperands, &mapSymTypes, &mapSymLocs, &mapSymbols);
2814- cp.processTODO <Fortran::parser::OmpClause::Private,
2815- Fortran::parser::OmpClause::Depend,
2840+ cp.processTODO <Fortran::parser::OmpClause::Depend,
28162841 Fortran::parser::OmpClause::Firstprivate,
28172842 Fortran::parser::OmpClause::IsDevicePtr,
28182843 Fortran::parser::OmpClause::HasDeviceAddr,
@@ -2823,11 +2848,21 @@ genTargetOp(Fortran::lower::AbstractConverter &converter,
28232848 Fortran::parser::OmpClause::Defaultmap>(
28242849 currentLocation, llvm::omp::Directive::OMPD_target);
28252850
2851+ DataSharingProcessor dsp (converter, clauseList, eval);
2852+ dsp.processStep1 ();
2853+
28262854 // 5.8.1 Implicit Data-Mapping Attribute Rules
28272855 // The following code follows the implicit data-mapping rules to map all the
2828- // symbols used inside the region that have not been explicitly mapped using
2829- // the map clause.
2856+ // symbols used inside the region that do not have explicit data-environment
2857+ // attribute clauses (neither data-sharing; e.g. `private`, nor `map`
2858+ // clauses).
28302859 auto captureImplicitMap = [&](const Fortran::semantics::Symbol &sym) {
2860+ if (dsp.getPrivatizedSymbols ().contains (&sym)) {
2861+ llvm::errs () << " sym is to be privatized: " << sym.name ().ToString ()
2862+ << " \n " ;
2863+ return ;
2864+ }
2865+
28312866 if (llvm::find (mapSymbols, &sym) == mapSymbols.end ()) {
28322867 mlir::Value baseOp = converter.getSymbolAddress (sym);
28332868 if (!baseOp)
@@ -2893,7 +2928,7 @@ genTargetOp(Fortran::lower::AbstractConverter &converter,
28932928 nowaitAttr, mapOperands);
28942929
28952930 genBodyOfTargetOp (converter, eval, genNested, targetOp, mapSymTypes,
2896- mapSymLocs, mapSymbols, currentLocation);
2931+ mapSymLocs, mapSymbols, currentLocation, clauseList, dsp );
28972932
28982933 return targetOp;
28992934}
@@ -3127,6 +3162,7 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter,
31273162 fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
31283163 DataSharingProcessor dsp (converter, loopOpClauseList, eval);
31293164 dsp.processStep1 ();
3165+ dsp.processStep2 ();
31303166
31313167 Fortran::lower::StatementContext stmtCtx;
31323168 mlir::Value scheduleChunkClauseOperand, ifClauseOperand;
@@ -3179,6 +3215,7 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter,
31793215 fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
31803216 DataSharingProcessor dsp (converter, beginClauseList, eval);
31813217 dsp.processStep1 ();
3218+ dsp.processStep2 ();
31823219
31833220 Fortran::lower::StatementContext stmtCtx;
31843221 mlir::Value scheduleChunkClauseOperand;
0 commit comments