77// ===----------------------------------------------------------------------===//
88
99#include " flang/Optimizer/Builder/FIRBuilder.h"
10+ #include " flang/Optimizer/Builder/Todo.h"
1011#include " flang/Optimizer/Dialect/FIROps.h"
1112#include " flang/Optimizer/OpenMP/Passes.h"
1213#include " flang/Optimizer/OpenMP/Utils.h"
14+ #include " flang/Support/OpenMP-utils.h"
1315#include " mlir/Analysis/SliceAnalysis.h"
1416#include " mlir/Dialect/OpenMP/OpenMPDialect.h"
1517#include " mlir/IR/IRMapping.h"
@@ -308,10 +310,47 @@ class DoConcurrentConversion
308310 fir::DoConcurrentLoopOp loop, mlir::IRMapping &mapper,
309311 const mlir::omp::LoopNestOperands &clauseOps,
310312 bool isComposite) const {
313+ mlir::omp::WsloopOperands wsloopClauseOps;
314+
315+ // For `local` (and `local_init`) opernads, emit corresponding `private`
316+ // clauses and attach these clauses to the workshare loop.
317+ if (!loop.getLocalOperands ().empty ())
318+ for (auto [op, sym, arg] : llvm::zip_equal (
319+ loop.getLocalOperands (),
320+ loop.getLocalSymsAttr ().getAsRange <mlir::SymbolRefAttr>(),
321+ loop.getRegionLocalArgs ())) {
322+ auto localizer = mlir::SymbolTable::lookupNearestSymbolFrom<
323+ fir::LocalitySpecifierOp>(loop, sym);
324+ if (localizer.getLocalitySpecifierType () ==
325+ fir::LocalitySpecifierType::LocalInit)
326+ TODO (localizer.getLoc (),
327+ " local_init conversion is not supported yet" );
328+
329+ if (!localizer.getInitRegion ().empty ())
330+ TODO (localizer.getLoc (),
331+ " non-empty `init` regions are not supported yet" );
332+
333+ auto oldIP = rewriter.saveInsertionPoint ();
334+ rewriter.setInsertionPointAfter (localizer);
335+ auto privatizer = rewriter.create <mlir::omp::PrivateClauseOp>(
336+ localizer.getLoc (), sym.getLeafReference ().str () + " .omp" ,
337+ localizer.getTypeAttr ().getValue (),
338+ mlir::omp::DataSharingClauseType::Private);
339+ rewriter.restoreInsertionPoint (oldIP);
340+
341+ wsloopClauseOps.privateVars .push_back (op);
342+ wsloopClauseOps.privateSyms .push_back (
343+ mlir::SymbolRefAttr::get (privatizer));
344+ }
311345
312- auto wsloopOp = rewriter.create <mlir::omp::WsloopOp>(loop.getLoc ());
346+ auto wsloopOp =
347+ rewriter.create <mlir::omp::WsloopOp>(loop.getLoc (), wsloopClauseOps);
313348 wsloopOp.setComposite (isComposite);
314- rewriter.createBlock (&wsloopOp.getRegion ());
349+
350+ Fortran::common::openmp::EntryBlockArgs wsloopArgs;
351+ wsloopArgs.priv .vars = wsloopClauseOps.privateVars ;
352+ Fortran::common::openmp::genEntryBlock (rewriter, wsloopArgs,
353+ wsloopOp.getRegion ());
315354
316355 auto loopNestOp =
317356 rewriter.create <mlir::omp::LoopNestOp>(loop.getLoc (), clauseOps);
@@ -324,6 +363,18 @@ class DoConcurrentConversion
324363 rewriter.setInsertionPointToEnd (&loopNestOp.getRegion ().back ());
325364 rewriter.create <mlir::omp::YieldOp>(loop->getLoc ());
326365
366+ // `local` region arguments are transferred/cloned from the `do concurrent`
367+ // loop to the loopnest op when the region is cloned above. Instead, these
368+ // region arguments should be on the workshare loop's region.
369+ for (auto [wsloopArg, loopNestArg] :
370+ llvm::zip_equal (wsloopOp.getRegion ().getArguments (),
371+ loopNestOp.getRegion ().getArguments ().drop_front (
372+ clauseOps.loopLowerBounds .size ())))
373+ rewriter.replaceAllUsesWith (loopNestArg, wsloopArg);
374+
375+ for (unsigned i = 0 ; i < loop.getLocalVars ().size (); ++i)
376+ loopNestOp.getRegion ().eraseArgument (clauseOps.loopLowerBounds .size ());
377+
327378 return loopNestOp;
328379 }
329380
0 commit comments