@@ -147,6 +147,14 @@ static void genNestedEvaluations(Fortran::lower::AbstractConverter &converter,
147
147
// ===----------------------------------------------------------------------===//
148
148
149
149
class DataSharingProcessor {
150
+ public:
151
+ struct DelayedPrivatizationInfo {
152
+ llvm::SetVector<mlir::SymbolRefAttr> privatizers;
153
+ llvm::SetVector<mlir::Value> hostAddresses;
154
+ llvm::SetVector<const Fortran::semantics::Symbol *> hostSymbols;
155
+ };
156
+
157
+ private:
150
158
bool hasLastPrivateOp;
151
159
mlir::OpBuilder::InsertPoint lastPrivIP;
152
160
mlir::OpBuilder::InsertPoint insPt;
@@ -163,8 +171,8 @@ class DataSharingProcessor {
163
171
164
172
bool useDelayedPrivatizationWhenPossible;
165
173
Fortran::lower::SymMap *symTable;
166
- llvm::SetVector<mlir::SymbolRefAttr> privatizers;
167
- llvm::SetVector<mlir::Value> privateSymHostAddrsses ;
174
+
175
+ DelayedPrivatizationInfo delayedPrivatizationInfo ;
168
176
169
177
bool needBarrier ();
170
178
void collectSymbols (Fortran::semantics::Symbol::Flag flag);
@@ -214,12 +222,8 @@ class DataSharingProcessor {
214
222
loopIV = iv;
215
223
}
216
224
217
- const llvm::SetVector<mlir::SymbolRefAttr> &getPrivatizers () const {
218
- return privatizers;
219
- };
220
-
221
- const llvm::SetVector<mlir::Value> &getPrivateSymHostAddrsses () const {
222
- return privateSymHostAddrsses;
225
+ const DelayedPrivatizationInfo &getDelayedPrivatizationInfo () const {
226
+ return delayedPrivatizationInfo;
223
227
}
224
228
};
225
229
@@ -547,8 +551,10 @@ void DataSharingProcessor::privatize() {
547
551
symTable->popScope ();
548
552
firOpBuilder.restoreInsertionPoint (ip);
549
553
550
- privatizers.insert (mlir::SymbolRefAttr::get (privatizerOp));
551
- privateSymHostAddrsses.insert (hsb.getAddr ());
554
+ delayedPrivatizationInfo.privatizers .insert (
555
+ mlir::SymbolRefAttr::get (privatizerOp));
556
+ delayedPrivatizationInfo.hostAddresses .insert (hsb.getAddr ());
557
+ delayedPrivatizationInfo.hostSymbols .insert (sym);
552
558
} else {
553
559
cloneSymbol (sym);
554
560
copyFirstPrivateSymbol (sym);
@@ -2305,7 +2311,9 @@ static void createBodyOfOp(
2305
2311
Op &op, Fortran::lower::AbstractConverter &converter, mlir::Location &loc,
2306
2312
Fortran::lower::pft::Evaluation &eval, bool genNested,
2307
2313
const Fortran::parser::OmpClauseList *clauses = nullptr ,
2308
- const llvm::SmallVector<const Fortran::semantics::Symbol *> &args = {},
2314
+ std::function<llvm::SmallVector<const Fortran::semantics::Symbol *>(
2315
+ mlir::Operation *)>
2316
+ genRegionEntryCB = nullptr,
2309
2317
bool outerCombined = false, DataSharingProcessor *dsp = nullptr) {
2310
2318
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
2311
2319
@@ -2319,27 +2327,15 @@ static void createBodyOfOp(
2319
2327
// argument. Also update the symbol's address with the mlir argument value.
2320
2328
// e.g. For loops the argument is the induction variable. And all further
2321
2329
// uses of the induction variable should use this mlir value.
2322
- if (args.size ()) {
2323
- std::size_t loopVarTypeSize = 0 ;
2324
- for (const Fortran::semantics::Symbol *arg : args)
2325
- loopVarTypeSize = std::max (loopVarTypeSize, arg->GetUltimate ().size ());
2326
- mlir::Type loopVarType = getLoopVarType (converter, loopVarTypeSize);
2327
- llvm::SmallVector<mlir::Type> tiv (args.size (), loopVarType);
2328
- llvm::SmallVector<mlir::Location> locs (args.size (), loc);
2329
- firOpBuilder.createBlock (&op.getRegion (), {}, tiv, locs);
2330
- // The argument is not currently in memory, so make a temporary for the
2331
- // argument, and store it there, then bind that location to the argument.
2332
- mlir::Operation *storeOp = nullptr ;
2333
- for (auto [argIndex, argSymbol] : llvm::enumerate (args)) {
2334
- mlir::Value indexVal =
2335
- fir::getBase (op.getRegion ().front ().getArgument (argIndex));
2336
- storeOp =
2337
- createAndSetPrivatizedLoopVar (converter, loc, indexVal, argSymbol);
2330
+ auto regionArgs =
2331
+ [&]() -> llvm::SmallVector<const Fortran::semantics::Symbol *> {
2332
+ if (genRegionEntryCB != nullptr ) {
2333
+ return genRegionEntryCB (op);
2338
2334
}
2339
- firOpBuilder.setInsertionPointAfter (storeOp);
2340
- } else {
2335
+
2341
2336
firOpBuilder.createBlock (&op.getRegion ());
2342
- }
2337
+ return {};
2338
+ }();
2343
2339
2344
2340
// Mark the earliest insertion point.
2345
2341
mlir::Operation *marker = insertMarker (firOpBuilder);
@@ -2437,8 +2433,8 @@ static void createBodyOfOp(
2437
2433
assert (tempDsp.has_value ());
2438
2434
tempDsp->processStep2 (op, isLoop);
2439
2435
} else {
2440
- if (isLoop && args .size () > 0 )
2441
- dsp->setLoopIV (converter.getSymbolAddress (*args [0 ]));
2436
+ if (isLoop && regionArgs .size () > 0 )
2437
+ dsp->setLoopIV (converter.getSymbolAddress (*regionArgs [0 ]));
2442
2438
dsp->processStep2 (op, isLoop);
2443
2439
}
2444
2440
}
@@ -2514,41 +2510,44 @@ static void genBodyOfTargetDataOp(
2514
2510
}
2515
2511
2516
2512
template <typename OpTy, typename ... Args>
2517
- static OpTy genOpWithBody (Fortran::lower::AbstractConverter &converter,
2518
- Fortran::lower::pft::Evaluation &eval, bool genNested,
2519
- mlir::Location currentLocation, bool outerCombined,
2520
- const Fortran::parser::OmpClauseList *clauseList,
2521
- DataSharingProcessor *dsp, Args &&...args) {
2513
+ static OpTy genOpWithBody (
2514
+ Fortran::lower::AbstractConverter &converter,
2515
+ Fortran::lower::pft::Evaluation &eval, bool genNested,
2516
+ mlir::Location currentLocation, bool outerCombined,
2517
+ const Fortran::parser::OmpClauseList *clauseList,
2518
+ std::function<llvm::SmallVector<const Fortran::semantics::Symbol *>(
2519
+ mlir::Operation *)>
2520
+ genRegionEntryCB,
2521
+ DataSharingProcessor *dsp, Args &&...args) {
2522
2522
auto op = converter.getFirOpBuilder ().create <OpTy>(
2523
2523
currentLocation, std::forward<Args>(args)...);
2524
2524
createBodyOfOp<OpTy>(op, converter, currentLocation, eval, genNested,
2525
- clauseList,
2526
- /* args=*/ {}, outerCombined, dsp);
2525
+ clauseList, genRegionEntryCB, outerCombined, dsp);
2527
2526
return op;
2528
2527
}
2529
2528
2530
2529
static mlir::omp::MasterOp
2531
2530
genMasterOp (Fortran::lower::AbstractConverter &converter,
2532
2531
Fortran::lower::pft::Evaluation &eval, bool genNested,
2533
2532
mlir::Location currentLocation) {
2534
- return genOpWithBody<mlir::omp::MasterOp>(converter, eval, genNested,
2535
- currentLocation,
2536
- /* outerCombined=*/ false ,
2537
- /* clauseList=*/ nullptr ,
2538
- /* dsp=*/ nullptr ,
2539
- /* resultTypes=*/ mlir::TypeRange ());
2533
+ return genOpWithBody<mlir::omp::MasterOp>(
2534
+ converter, eval, genNested, currentLocation,
2535
+ /* outerCombined=*/ false ,
2536
+ /* clauseList= */ nullptr , /* genRegionEntryCB =*/ nullptr ,
2537
+ /* dsp=*/ nullptr ,
2538
+ /* resultTypes=*/ mlir::TypeRange ());
2540
2539
}
2541
2540
2542
2541
static mlir::omp::OrderedRegionOp
2543
2542
genOrderedRegionOp (Fortran::lower::AbstractConverter &converter,
2544
2543
Fortran::lower::pft::Evaluation &eval, bool genNested,
2545
2544
mlir::Location currentLocation) {
2546
- return genOpWithBody<mlir::omp::OrderedRegionOp>(converter, eval, genNested,
2547
- currentLocation,
2548
- /* outerCombined=*/ false ,
2549
- /* clauseList=*/ nullptr ,
2550
- /* dsp=*/ nullptr ,
2551
- /* simd=*/ false );
2545
+ return genOpWithBody<mlir::omp::OrderedRegionOp>(
2546
+ converter, eval, genNested, currentLocation,
2547
+ /* outerCombined=*/ false ,
2548
+ /* clauseList= */ nullptr , /* genRegionEntryCB =*/ nullptr ,
2549
+ /* dsp=*/ nullptr ,
2550
+ /* simd=*/ false );
2552
2551
}
2553
2552
2554
2553
static mlir::omp::ParallelOp
@@ -2584,16 +2583,44 @@ genParallelOp(Fortran::lower::AbstractConverter &converter,
2584
2583
dsp.processStep1 ();
2585
2584
}
2586
2585
2587
- llvm::SmallVector<mlir::Attribute> privatizers (dsp.getPrivatizers ().begin (),
2588
- dsp.getPrivatizers ().end ());
2586
+ const auto &delayedPrivatizationInfo = dsp.getDelayedPrivatizationInfo ();
2587
+ llvm::SmallVector<mlir::Attribute> privatizers (
2588
+ delayedPrivatizationInfo.privatizers .begin (),
2589
+ delayedPrivatizationInfo.privatizers .end ());
2589
2590
2590
2591
llvm::SmallVector<mlir::Value> privateSymAddresses (
2591
- dsp.getPrivateSymHostAddrsses ().begin (),
2592
- dsp.getPrivateSymHostAddrsses ().end ());
2592
+ delayedPrivatizationInfo.hostAddresses .begin (),
2593
+ delayedPrivatizationInfo.hostAddresses .end ());
2594
+
2595
+ auto genRegionEntryCB = [&](mlir::Operation *op) {
2596
+ auto parallelOp = llvm::cast<mlir::omp::ParallelOp>(op);
2597
+ auto privateVars = parallelOp.getPrivateVars ();
2598
+ auto ®ion = parallelOp.getRegion ();
2599
+ llvm::SmallVector<mlir::Type> privateVarTypes;
2600
+ llvm::SmallVector<mlir::Location> privateVarLocs;
2601
+
2602
+ for (auto privateVar : privateVars) {
2603
+ privateVarTypes.push_back (privateVar.getType ());
2604
+ privateVarLocs.push_back (privateVar.getLoc ());
2605
+ }
2606
+
2607
+ converter.getFirOpBuilder ().createBlock (®ion, {}, privateVarTypes,
2608
+ privateVarLocs);
2609
+
2610
+ int argIdx = 0 ;
2611
+ for (const auto *sym : delayedPrivatizationInfo.hostSymbols ) {
2612
+ converter.bindSymbol (*sym, region.getArgument (argIdx));
2613
+ ++argIdx;
2614
+ }
2615
+
2616
+ return llvm::SmallVector<const Fortran::semantics::Symbol *>(
2617
+ delayedPrivatizationInfo.hostSymbols .begin (),
2618
+ delayedPrivatizationInfo.hostSymbols .end ());
2619
+ };
2593
2620
2594
2621
return genOpWithBody<mlir::omp::ParallelOp>(
2595
2622
converter, eval, genNested, currentLocation, outerCombined, &clauseList,
2596
- &dsp,
2623
+ genRegionEntryCB, &dsp,
2597
2624
/* resultTypes=*/ mlir::TypeRange (), ifClauseOperand,
2598
2625
numThreadsClauseOperand, allocateOperands, allocatorOperands,
2599
2626
reductionVars,
@@ -2618,6 +2645,7 @@ genSectionOp(Fortran::lower::AbstractConverter &converter,
2618
2645
return genOpWithBody<mlir::omp::SectionOp>(
2619
2646
converter, eval, genNested, currentLocation,
2620
2647
/* outerCombined=*/ false , §ionsClauseList,
2648
+ /* genRegionEntryCB=*/ nullptr ,
2621
2649
/* dsp=*/ nullptr );
2622
2650
}
2623
2651
@@ -2639,8 +2667,8 @@ genSingleOp(Fortran::lower::AbstractConverter &converter,
2639
2667
2640
2668
return genOpWithBody<mlir::omp::SingleOp>(
2641
2669
converter, eval, genNested, currentLocation,
2642
- /* outerCombined=*/ false , &beginClauseList, /* dsp =*/ nullptr ,
2643
- allocateOperands, allocatorOperands, nowaitAttr);
2670
+ /* outerCombined=*/ false , &beginClauseList, /* genRegionEntryCB =*/ nullptr ,
2671
+ /* dsp= */ nullptr , allocateOperands, allocatorOperands, nowaitAttr);
2644
2672
}
2645
2673
2646
2674
static mlir::omp::TaskOp
@@ -2672,8 +2700,9 @@ genTaskOp(Fortran::lower::AbstractConverter &converter,
2672
2700
2673
2701
return genOpWithBody<mlir::omp::TaskOp>(
2674
2702
converter, eval, genNested, currentLocation,
2675
- /* outerCombined=*/ false , &clauseList, /* dsp=*/ nullptr , ifClauseOperand,
2676
- finalClauseOperand, untiedAttr, mergeableAttr,
2703
+ /* outerCombined=*/ false , &clauseList, /* genRegionEntryCB=*/ nullptr ,
2704
+ /* dsp=*/ nullptr , ifClauseOperand, finalClauseOperand, untiedAttr,
2705
+ mergeableAttr,
2677
2706
/* in_reduction_vars=*/ mlir::ValueRange (),
2678
2707
/* in_reductions=*/ nullptr , priorityClauseOperand,
2679
2708
dependTypeOperands.empty ()
@@ -2695,7 +2724,7 @@ genTaskGroupOp(Fortran::lower::AbstractConverter &converter,
2695
2724
currentLocation, llvm::omp::Directive::OMPD_taskgroup);
2696
2725
return genOpWithBody<mlir::omp::TaskGroupOp>(
2697
2726
converter, eval, genNested, currentLocation,
2698
- /* outerCombined=*/ false , &clauseList,
2727
+ /* outerCombined=*/ false , &clauseList, /* genRegionEntryCB= */ nullptr ,
2699
2728
/* dsp=*/ nullptr ,
2700
2729
/* task_reduction_vars=*/ mlir::ValueRange (),
2701
2730
/* task_reductions=*/ nullptr , allocateOperands, allocatorOperands);
@@ -3076,6 +3105,7 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter,
3076
3105
3077
3106
return genOpWithBody<mlir::omp::TeamsOp>(
3078
3107
converter, eval, genNested, currentLocation, outerCombined, &clauseList,
3108
+ /* genRegionEntryCB=*/ nullptr ,
3079
3109
/* dsp=*/ nullptr ,
3080
3110
/* num_teams_lower=*/ nullptr , numTeamsClauseOperand, ifClauseOperand,
3081
3111
threadLimitClauseOperand, allocateOperands, allocatorOperands,
@@ -3273,6 +3303,33 @@ static void convertLoopBounds(Fortran::lower::AbstractConverter &converter,
3273
3303
}
3274
3304
}
3275
3305
3306
+ static llvm::SmallVector<const Fortran::semantics::Symbol *> genCodeForIterVar (
3307
+ mlir::Operation *op, Fortran::lower::AbstractConverter &converter,
3308
+ mlir::Location &loc,
3309
+ const llvm::SmallVector<const Fortran::semantics::Symbol *> &args) {
3310
+ fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
3311
+ auto ®ion = op->getRegion (0 );
3312
+
3313
+ std::size_t loopVarTypeSize = 0 ;
3314
+ for (const Fortran::semantics::Symbol *arg : args)
3315
+ loopVarTypeSize = std::max (loopVarTypeSize, arg->GetUltimate ().size ());
3316
+ mlir::Type loopVarType = getLoopVarType (converter, loopVarTypeSize);
3317
+ llvm::SmallVector<mlir::Type> tiv (args.size (), loopVarType);
3318
+ llvm::SmallVector<mlir::Location> locs (args.size (), loc);
3319
+ firOpBuilder.createBlock (®ion, {}, tiv, locs);
3320
+ // The argument is not currently in memory, so make a temporary for the
3321
+ // argument, and store it there, then bind that location to the argument.
3322
+ mlir::Operation *storeOp = nullptr ;
3323
+ for (auto [argIndex, argSymbol] : llvm::enumerate (args)) {
3324
+ mlir::Value indexVal = fir::getBase (region.front ().getArgument (argIndex));
3325
+ storeOp =
3326
+ createAndSetPrivatizedLoopVar (converter, loc, indexVal, argSymbol);
3327
+ }
3328
+ firOpBuilder.setInsertionPointAfter (storeOp);
3329
+
3330
+ return args;
3331
+ }
3332
+
3276
3333
static void
3277
3334
createSimdLoop (Fortran::lower::AbstractConverter &converter,
3278
3335
Fortran::lower::pft::Evaluation &eval,
@@ -3320,9 +3377,14 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter,
3320
3377
3321
3378
auto *nestedEval = getCollapsedLoopEval (
3322
3379
eval, Fortran::lower::getCollapseValue (loopOpClauseList));
3380
+
3381
+ auto ivCallback = [&](mlir::Operation *op) {
3382
+ return genCodeForIterVar (op, converter, loc, iv);
3383
+ };
3384
+
3323
3385
createBodyOfOp<mlir::omp::SimdLoopOp>(simdLoopOp, converter, loc, *nestedEval,
3324
3386
/* genNested=*/ true , &loopOpClauseList,
3325
- iv , /* outer=*/ false , &dsp);
3387
+ ivCallback , /* outer=*/ false , &dsp);
3326
3388
}
3327
3389
3328
3390
static void createWsLoop (Fortran::lower::AbstractConverter &converter,
@@ -3395,8 +3457,14 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter,
3395
3457
3396
3458
auto *nestedEval = getCollapsedLoopEval (
3397
3459
eval, Fortran::lower::getCollapseValue (beginClauseList));
3460
+
3461
+ auto ivCallback = [&](mlir::Operation *op) {
3462
+ return genCodeForIterVar (op, converter, loc, iv);
3463
+ };
3464
+
3398
3465
createBodyOfOp<mlir::omp::WsLoopOp>(wsLoopOp, converter, loc, *nestedEval,
3399
- /* genNested=*/ true , &beginClauseList, iv,
3466
+ /* genNested=*/ true , &beginClauseList,
3467
+ ivCallback,
3400
3468
/* outer=*/ false , &dsp);
3401
3469
}
3402
3470
@@ -3725,6 +3793,7 @@ genOMP(Fortran::lower::AbstractConverter &converter,
3725
3793
/* genNested=*/ false , currentLocation,
3726
3794
/* outerCombined=*/ false ,
3727
3795
/* clauseList=*/ nullptr ,
3796
+ /* genRegionEntryCB=*/ nullptr ,
3728
3797
/* dsp=*/ nullptr ,
3729
3798
/* reduction_vars=*/ mlir::ValueRange (),
3730
3799
/* reductions=*/ nullptr , allocateOperands,
0 commit comments