@@ -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);
@@ -2322,7 +2328,9 @@ static void createBodyOfOp(
2322
2328
Op &op, Fortran::lower::AbstractConverter &converter, mlir::Location &loc,
2323
2329
Fortran::lower::pft::Evaluation &eval, bool genNested,
2324
2330
const Fortran::parser::OmpClauseList *clauses = nullptr ,
2325
- const llvm::SmallVector<const Fortran::semantics::Symbol *> &args = {},
2331
+ std::function<llvm::SmallVector<const Fortran::semantics::Symbol *>(
2332
+ mlir::Operation *)>
2333
+ genRegionEntryCB = nullptr,
2326
2334
bool outerCombined = false, DataSharingProcessor *dsp = nullptr) {
2327
2335
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
2328
2336
@@ -2336,27 +2344,15 @@ static void createBodyOfOp(
2336
2344
// argument. Also update the symbol's address with the mlir argument value.
2337
2345
// e.g. For loops the argument is the induction variable. And all further
2338
2346
// uses of the induction variable should use this mlir value.
2339
- if (args.size ()) {
2340
- std::size_t loopVarTypeSize = 0 ;
2341
- for (const Fortran::semantics::Symbol *arg : args)
2342
- loopVarTypeSize = std::max (loopVarTypeSize, arg->GetUltimate ().size ());
2343
- mlir::Type loopVarType = getLoopVarType (converter, loopVarTypeSize);
2344
- llvm::SmallVector<mlir::Type> tiv (args.size (), loopVarType);
2345
- llvm::SmallVector<mlir::Location> locs (args.size (), loc);
2346
- firOpBuilder.createBlock (&op.getRegion (), {}, tiv, locs);
2347
- // The argument is not currently in memory, so make a temporary for the
2348
- // argument, and store it there, then bind that location to the argument.
2349
- mlir::Operation *storeOp = nullptr ;
2350
- for (auto [argIndex, argSymbol] : llvm::enumerate (args)) {
2351
- mlir::Value indexVal =
2352
- fir::getBase (op.getRegion ().front ().getArgument (argIndex));
2353
- storeOp =
2354
- createAndSetPrivatizedLoopVar (converter, loc, indexVal, argSymbol);
2347
+ auto regionArgs =
2348
+ [&]() -> llvm::SmallVector<const Fortran::semantics::Symbol *> {
2349
+ if (genRegionEntryCB != nullptr ) {
2350
+ return genRegionEntryCB (op);
2355
2351
}
2356
- firOpBuilder.setInsertionPointAfter (storeOp);
2357
- } else {
2352
+
2358
2353
firOpBuilder.createBlock (&op.getRegion ());
2359
- }
2354
+ return {};
2355
+ }();
2360
2356
2361
2357
// Mark the earliest insertion point.
2362
2358
mlir::Operation *marker = insertMarker (firOpBuilder);
@@ -2454,8 +2450,8 @@ static void createBodyOfOp(
2454
2450
assert (tempDsp.has_value ());
2455
2451
tempDsp->processStep2 (op, isLoop);
2456
2452
} else {
2457
- if (isLoop && args .size () > 0 )
2458
- dsp->setLoopIV (converter.getSymbolAddress (*args [0 ]));
2453
+ if (isLoop && regionArgs .size () > 0 )
2454
+ dsp->setLoopIV (converter.getSymbolAddress (*regionArgs [0 ]));
2459
2455
dsp->processStep2 (op, isLoop);
2460
2456
}
2461
2457
}
@@ -2531,41 +2527,44 @@ static void genBodyOfTargetDataOp(
2531
2527
}
2532
2528
2533
2529
template <typename OpTy, typename ... Args>
2534
- static OpTy genOpWithBody (Fortran::lower::AbstractConverter &converter,
2535
- Fortran::lower::pft::Evaluation &eval, bool genNested,
2536
- mlir::Location currentLocation, bool outerCombined,
2537
- const Fortran::parser::OmpClauseList *clauseList,
2538
- DataSharingProcessor *dsp, Args &&...args) {
2530
+ static OpTy genOpWithBody (
2531
+ Fortran::lower::AbstractConverter &converter,
2532
+ Fortran::lower::pft::Evaluation &eval, bool genNested,
2533
+ mlir::Location currentLocation, bool outerCombined,
2534
+ const Fortran::parser::OmpClauseList *clauseList,
2535
+ std::function<llvm::SmallVector<const Fortran::semantics::Symbol *>(
2536
+ mlir::Operation *)>
2537
+ genRegionEntryCB,
2538
+ DataSharingProcessor *dsp, Args &&...args) {
2539
2539
auto op = converter.getFirOpBuilder ().create <OpTy>(
2540
2540
currentLocation, std::forward<Args>(args)...);
2541
2541
createBodyOfOp<OpTy>(op, converter, currentLocation, eval, genNested,
2542
- clauseList,
2543
- /* args=*/ {}, outerCombined, dsp);
2542
+ clauseList, genRegionEntryCB, outerCombined, dsp);
2544
2543
return op;
2545
2544
}
2546
2545
2547
2546
static mlir::omp::MasterOp
2548
2547
genMasterOp (Fortran::lower::AbstractConverter &converter,
2549
2548
Fortran::lower::pft::Evaluation &eval, bool genNested,
2550
2549
mlir::Location currentLocation) {
2551
- return genOpWithBody<mlir::omp::MasterOp>(converter, eval, genNested,
2552
- currentLocation,
2553
- /* outerCombined=*/ false ,
2554
- /* clauseList=*/ nullptr ,
2555
- /* dsp=*/ nullptr ,
2556
- /* resultTypes=*/ mlir::TypeRange ());
2550
+ return genOpWithBody<mlir::omp::MasterOp>(
2551
+ converter, eval, genNested, currentLocation,
2552
+ /* outerCombined=*/ false ,
2553
+ /* clauseList= */ nullptr , /* genRegionEntryCB =*/ nullptr ,
2554
+ /* dsp=*/ nullptr ,
2555
+ /* resultTypes=*/ mlir::TypeRange ());
2557
2556
}
2558
2557
2559
2558
static mlir::omp::OrderedRegionOp
2560
2559
genOrderedRegionOp (Fortran::lower::AbstractConverter &converter,
2561
2560
Fortran::lower::pft::Evaluation &eval, bool genNested,
2562
2561
mlir::Location currentLocation) {
2563
- return genOpWithBody<mlir::omp::OrderedRegionOp>(converter, eval, genNested,
2564
- currentLocation,
2565
- /* outerCombined=*/ false ,
2566
- /* clauseList=*/ nullptr ,
2567
- /* dsp=*/ nullptr ,
2568
- /* simd=*/ false );
2562
+ return genOpWithBody<mlir::omp::OrderedRegionOp>(
2563
+ converter, eval, genNested, currentLocation,
2564
+ /* outerCombined=*/ false ,
2565
+ /* clauseList= */ nullptr , /* genRegionEntryCB =*/ nullptr ,
2566
+ /* dsp=*/ nullptr ,
2567
+ /* simd=*/ false );
2569
2568
}
2570
2569
2571
2570
static mlir::omp::ParallelOp
@@ -2601,16 +2600,44 @@ genParallelOp(Fortran::lower::AbstractConverter &converter,
2601
2600
dsp.processStep1 ();
2602
2601
}
2603
2602
2604
- llvm::SmallVector<mlir::Attribute> privatizers (dsp.getPrivatizers ().begin (),
2605
- dsp.getPrivatizers ().end ());
2603
+ const auto &delayedPrivatizationInfo = dsp.getDelayedPrivatizationInfo ();
2604
+ llvm::SmallVector<mlir::Attribute> privatizers (
2605
+ delayedPrivatizationInfo.privatizers .begin (),
2606
+ delayedPrivatizationInfo.privatizers .end ());
2606
2607
2607
2608
llvm::SmallVector<mlir::Value> privateSymAddresses (
2608
- dsp.getPrivateSymHostAddrsses ().begin (),
2609
- dsp.getPrivateSymHostAddrsses ().end ());
2609
+ delayedPrivatizationInfo.hostAddresses .begin (),
2610
+ delayedPrivatizationInfo.hostAddresses .end ());
2611
+
2612
+ auto genRegionEntryCB = [&](mlir::Operation *op) {
2613
+ auto parallelOp = llvm::cast<mlir::omp::ParallelOp>(op);
2614
+ auto privateVars = parallelOp.getPrivateVars ();
2615
+ auto ®ion = parallelOp.getRegion ();
2616
+ llvm::SmallVector<mlir::Type> privateVarTypes;
2617
+ llvm::SmallVector<mlir::Location> privateVarLocs;
2618
+
2619
+ for (auto privateVar : privateVars) {
2620
+ privateVarTypes.push_back (privateVar.getType ());
2621
+ privateVarLocs.push_back (privateVar.getLoc ());
2622
+ }
2623
+
2624
+ converter.getFirOpBuilder ().createBlock (®ion, {}, privateVarTypes,
2625
+ privateVarLocs);
2626
+
2627
+ int argIdx = 0 ;
2628
+ for (const auto *sym : delayedPrivatizationInfo.hostSymbols ) {
2629
+ converter.bindSymbol (*sym, region.getArgument (argIdx));
2630
+ ++argIdx;
2631
+ }
2632
+
2633
+ return llvm::SmallVector<const Fortran::semantics::Symbol *>(
2634
+ delayedPrivatizationInfo.hostSymbols .begin (),
2635
+ delayedPrivatizationInfo.hostSymbols .end ());
2636
+ };
2610
2637
2611
2638
return genOpWithBody<mlir::omp::ParallelOp>(
2612
2639
converter, eval, genNested, currentLocation, outerCombined, &clauseList,
2613
- &dsp,
2640
+ genRegionEntryCB, &dsp,
2614
2641
/* resultTypes=*/ mlir::TypeRange (), ifClauseOperand,
2615
2642
numThreadsClauseOperand, allocateOperands, allocatorOperands,
2616
2643
reductionVars,
@@ -2635,6 +2662,7 @@ genSectionOp(Fortran::lower::AbstractConverter &converter,
2635
2662
return genOpWithBody<mlir::omp::SectionOp>(
2636
2663
converter, eval, genNested, currentLocation,
2637
2664
/* outerCombined=*/ false , §ionsClauseList,
2665
+ /* genRegionEntryCB=*/ nullptr ,
2638
2666
/* dsp=*/ nullptr );
2639
2667
}
2640
2668
@@ -2656,8 +2684,8 @@ genSingleOp(Fortran::lower::AbstractConverter &converter,
2656
2684
2657
2685
return genOpWithBody<mlir::omp::SingleOp>(
2658
2686
converter, eval, genNested, currentLocation,
2659
- /* outerCombined=*/ false , &beginClauseList, /* dsp =*/ nullptr ,
2660
- allocateOperands, allocatorOperands, nowaitAttr);
2687
+ /* outerCombined=*/ false , &beginClauseList, /* genRegionEntryCB =*/ nullptr ,
2688
+ /* dsp= */ nullptr , allocateOperands, allocatorOperands, nowaitAttr);
2661
2689
}
2662
2690
2663
2691
static mlir::omp::TaskOp
@@ -2689,8 +2717,9 @@ genTaskOp(Fortran::lower::AbstractConverter &converter,
2689
2717
2690
2718
return genOpWithBody<mlir::omp::TaskOp>(
2691
2719
converter, eval, genNested, currentLocation,
2692
- /* outerCombined=*/ false , &clauseList, /* dsp=*/ nullptr , ifClauseOperand,
2693
- finalClauseOperand, untiedAttr, mergeableAttr,
2720
+ /* outerCombined=*/ false , &clauseList, /* genRegionEntryCB=*/ nullptr ,
2721
+ /* dsp=*/ nullptr , ifClauseOperand, finalClauseOperand, untiedAttr,
2722
+ mergeableAttr,
2694
2723
/* in_reduction_vars=*/ mlir::ValueRange (),
2695
2724
/* in_reductions=*/ nullptr , priorityClauseOperand,
2696
2725
dependTypeOperands.empty ()
@@ -2712,7 +2741,7 @@ genTaskGroupOp(Fortran::lower::AbstractConverter &converter,
2712
2741
currentLocation, llvm::omp::Directive::OMPD_taskgroup);
2713
2742
return genOpWithBody<mlir::omp::TaskGroupOp>(
2714
2743
converter, eval, genNested, currentLocation,
2715
- /* outerCombined=*/ false , &clauseList,
2744
+ /* outerCombined=*/ false , &clauseList, /* genRegionEntryCB= */ nullptr ,
2716
2745
/* dsp=*/ nullptr ,
2717
2746
/* task_reduction_vars=*/ mlir::ValueRange (),
2718
2747
/* task_reductions=*/ nullptr , allocateOperands, allocatorOperands);
@@ -3097,6 +3126,7 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter,
3097
3126
3098
3127
return genOpWithBody<mlir::omp::TeamsOp>(
3099
3128
converter, eval, genNested, currentLocation, outerCombined, &clauseList,
3129
+ /* genRegionEntryCB=*/ nullptr ,
3100
3130
/* dsp=*/ nullptr ,
3101
3131
/* num_teams_lower=*/ nullptr , numTeamsClauseOperand, ifClauseOperand,
3102
3132
threadLimitClauseOperand, allocateOperands, allocatorOperands,
@@ -3294,6 +3324,33 @@ static void convertLoopBounds(Fortran::lower::AbstractConverter &converter,
3294
3324
}
3295
3325
}
3296
3326
3327
+ static llvm::SmallVector<const Fortran::semantics::Symbol *> genCodeForIterVar (
3328
+ mlir::Operation *op, Fortran::lower::AbstractConverter &converter,
3329
+ mlir::Location &loc,
3330
+ const llvm::SmallVector<const Fortran::semantics::Symbol *> &args) {
3331
+ fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
3332
+ auto ®ion = op->getRegion (0 );
3333
+
3334
+ std::size_t loopVarTypeSize = 0 ;
3335
+ for (const Fortran::semantics::Symbol *arg : args)
3336
+ loopVarTypeSize = std::max (loopVarTypeSize, arg->GetUltimate ().size ());
3337
+ mlir::Type loopVarType = getLoopVarType (converter, loopVarTypeSize);
3338
+ llvm::SmallVector<mlir::Type> tiv (args.size (), loopVarType);
3339
+ llvm::SmallVector<mlir::Location> locs (args.size (), loc);
3340
+ firOpBuilder.createBlock (®ion, {}, tiv, locs);
3341
+ // The argument is not currently in memory, so make a temporary for the
3342
+ // argument, and store it there, then bind that location to the argument.
3343
+ mlir::Operation *storeOp = nullptr ;
3344
+ for (auto [argIndex, argSymbol] : llvm::enumerate (args)) {
3345
+ mlir::Value indexVal = fir::getBase (region.front ().getArgument (argIndex));
3346
+ storeOp =
3347
+ createAndSetPrivatizedLoopVar (converter, loc, indexVal, argSymbol);
3348
+ }
3349
+ firOpBuilder.setInsertionPointAfter (storeOp);
3350
+
3351
+ return args;
3352
+ }
3353
+
3297
3354
static void
3298
3355
createSimdLoop (Fortran::lower::AbstractConverter &converter,
3299
3356
Fortran::lower::pft::Evaluation &eval,
@@ -3341,9 +3398,14 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter,
3341
3398
3342
3399
auto *nestedEval = getCollapsedLoopEval (
3343
3400
eval, Fortran::lower::getCollapseValue (loopOpClauseList));
3401
+
3402
+ auto ivCallback = [&](mlir::Operation *op) {
3403
+ return genCodeForIterVar (op, converter, loc, iv);
3404
+ };
3405
+
3344
3406
createBodyOfOp<mlir::omp::SimdLoopOp>(simdLoopOp, converter, loc, *nestedEval,
3345
3407
/* genNested=*/ true , &loopOpClauseList,
3346
- iv , /* outer=*/ false , &dsp);
3408
+ ivCallback , /* outer=*/ false , &dsp);
3347
3409
}
3348
3410
3349
3411
static void createWsLoop (Fortran::lower::AbstractConverter &converter,
@@ -3416,8 +3478,14 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter,
3416
3478
3417
3479
auto *nestedEval = getCollapsedLoopEval (
3418
3480
eval, Fortran::lower::getCollapseValue (beginClauseList));
3481
+
3482
+ auto ivCallback = [&](mlir::Operation *op) {
3483
+ return genCodeForIterVar (op, converter, loc, iv);
3484
+ };
3485
+
3419
3486
createBodyOfOp<mlir::omp::WsLoopOp>(wsLoopOp, converter, loc, *nestedEval,
3420
- /* genNested=*/ true , &beginClauseList, iv,
3487
+ /* genNested=*/ true , &beginClauseList,
3488
+ ivCallback,
3421
3489
/* outer=*/ false , &dsp);
3422
3490
}
3423
3491
@@ -3746,6 +3814,7 @@ genOMP(Fortran::lower::AbstractConverter &converter,
3746
3814
/* genNested=*/ false , currentLocation,
3747
3815
/* outerCombined=*/ false ,
3748
3816
/* clauseList=*/ nullptr ,
3817
+ /* genRegionEntryCB=*/ nullptr ,
3749
3818
/* dsp=*/ nullptr ,
3750
3819
/* reduction_vars=*/ mlir::ValueRange (),
3751
3820
/* reductions=*/ nullptr , allocateOperands,
0 commit comments