7
7
// ===----------------------------------------------------------------------===//
8
8
9
9
#include " flang/Optimizer/Builder/FIRBuilder.h"
10
+ #include " flang/Optimizer/Builder/Todo.h"
10
11
#include " flang/Optimizer/Dialect/FIROps.h"
11
12
#include " flang/Optimizer/OpenMP/Passes.h"
12
13
#include " flang/Optimizer/OpenMP/Utils.h"
14
+ #include " flang/Support/OpenMP-utils.h"
13
15
#include " mlir/Analysis/SliceAnalysis.h"
14
16
#include " mlir/Dialect/OpenMP/OpenMPDialect.h"
15
17
#include " mlir/IR/IRMapping.h"
@@ -308,10 +310,47 @@ class DoConcurrentConversion
308
310
fir::DoConcurrentLoopOp loop, mlir::IRMapping &mapper,
309
311
const mlir::omp::LoopNestOperands &clauseOps,
310
312
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
+ }
311
345
312
- auto wsloopOp = rewriter.create <mlir::omp::WsloopOp>(loop.getLoc ());
346
+ auto wsloopOp =
347
+ rewriter.create <mlir::omp::WsloopOp>(loop.getLoc (), wsloopClauseOps);
313
348
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 ());
315
354
316
355
auto loopNestOp =
317
356
rewriter.create <mlir::omp::LoopNestOp>(loop.getLoc (), clauseOps);
@@ -324,6 +363,18 @@ class DoConcurrentConversion
324
363
rewriter.setInsertionPointToEnd (&loopNestOp.getRegion ().back ());
325
364
rewriter.create <mlir::omp::YieldOp>(loop->getLoc ());
326
365
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
+
327
378
return loopNestOp;
328
379
}
329
380
0 commit comments