@@ -94,10 +94,11 @@ struct IncrementLoopInfo {
94
94
template <typename T>
95
95
explicit IncrementLoopInfo (Fortran::semantics::Symbol &sym, const T &lower,
96
96
const T &upper, const std::optional<T> &step,
97
- bool isUnordered = false )
97
+ bool isConcurrent = false )
98
98
: loopVariableSym{&sym}, lowerExpr{Fortran::semantics::GetExpr (lower)},
99
99
upperExpr{Fortran::semantics::GetExpr (upper)},
100
- stepExpr{Fortran::semantics::GetExpr (step)}, isUnordered{isUnordered} {}
100
+ stepExpr{Fortran::semantics::GetExpr (step)},
101
+ isConcurrent{isConcurrent} {}
101
102
102
103
IncrementLoopInfo (IncrementLoopInfo &&) = default ;
103
104
IncrementLoopInfo &operator =(IncrementLoopInfo &&x) = default ;
@@ -120,7 +121,7 @@ struct IncrementLoopInfo {
120
121
const Fortran::lower::SomeExpr *upperExpr;
121
122
const Fortran::lower::SomeExpr *stepExpr;
122
123
const Fortran::lower::SomeExpr *maskExpr = nullptr ;
123
- bool isUnordered; // do concurrent, forall
124
+ bool isConcurrent;
124
125
llvm::SmallVector<const Fortran::semantics::Symbol *> localSymList;
125
126
llvm::SmallVector<const Fortran::semantics::Symbol *> localInitSymList;
126
127
llvm::SmallVector<
@@ -130,7 +131,7 @@ struct IncrementLoopInfo {
130
131
mlir::Value loopVariable = nullptr ;
131
132
132
133
// Data members for structured loops.
133
- fir::DoLoopOp doLoop = nullptr ;
134
+ mlir::Operation *loopOp = nullptr ;
134
135
135
136
// Data members for unstructured loops.
136
137
bool hasRealControl = false ;
@@ -1981,7 +1982,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1981
1982
llvm_unreachable (" illegal reduction operator" );
1982
1983
}
1983
1984
1984
- // / Collect DO CONCURRENT or FORALL loop control information.
1985
+ // / Collect DO CONCURRENT loop control information.
1985
1986
IncrementLoopNestInfo getConcurrentControl (
1986
1987
const Fortran::parser::ConcurrentHeader &header,
1987
1988
const std::list<Fortran::parser::LocalitySpec> &localityList = {}) {
@@ -2292,8 +2293,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2292
2293
mlir::LLVM::LoopAnnotationAttr la = mlir::LLVM::LoopAnnotationAttr::get (
2293
2294
builder->getContext (), {}, /* vectorize=*/ va, {}, /* unroll*/ ua,
2294
2295
/* unroll_and_jam*/ uja, {}, {}, {}, {}, {}, {}, {}, {}, {}, {});
2295
- if (has_attrs)
2296
- info.doLoop .setLoopAnnotationAttr (la);
2296
+ if (has_attrs) {
2297
+ if (auto loopOp = mlir::dyn_cast<fir::DoLoopOp>(info.loopOp ))
2298
+ loopOp.setLoopAnnotationAttr (la);
2299
+
2300
+ if (auto doConcurrentOp =
2301
+ mlir::dyn_cast<fir::DoConcurrentLoopOp>(info.loopOp ))
2302
+ doConcurrentOp.setLoopAnnotationAttr (la);
2303
+ }
2297
2304
}
2298
2305
2299
2306
// / Generate FIR to begin a structured or unstructured increment loop nest.
@@ -2302,96 +2309,77 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2302
2309
llvm::SmallVectorImpl<const Fortran::parser::CompilerDirective *> &dirs) {
2303
2310
assert (!incrementLoopNestInfo.empty () && " empty loop nest" );
2304
2311
mlir::Location loc = toLocation ();
2305
- mlir::Operation *boundsAndStepIP = nullptr ;
2306
2312
mlir::arith::IntegerOverflowFlags iofBackup{};
2307
2313
2314
+ llvm::SmallVector<mlir::Value> nestLBs;
2315
+ llvm::SmallVector<mlir::Value> nestUBs;
2316
+ llvm::SmallVector<mlir::Value> nestSts;
2317
+ llvm::SmallVector<mlir::Value> nestReduceOperands;
2318
+ llvm::SmallVector<mlir::Attribute> nestReduceAttrs;
2319
+ bool genDoConcurrent = false ;
2320
+
2308
2321
for (IncrementLoopInfo &info : incrementLoopNestInfo) {
2309
- mlir::Value lowerValue;
2310
- mlir::Value upperValue;
2311
- mlir::Value stepValue;
2322
+ genDoConcurrent = info.isStructured () && info.isConcurrent ;
2312
2323
2313
- {
2314
- mlir::OpBuilder::InsertionGuard guard (*builder);
2324
+ if (!genDoConcurrent)
2325
+ info.loopVariable = genLoopVariableAddress (loc, *info.loopVariableSym ,
2326
+ info.isConcurrent );
2315
2327
2316
- // Set the IP before the first loop in the nest so that all nest bounds
2317
- // and step values are created outside the nest.
2318
- if (boundsAndStepIP)
2319
- builder->setInsertionPointAfter (boundsAndStepIP);
2328
+ if (!getLoweringOptions ().getIntegerWrapAround ()) {
2329
+ iofBackup = builder->getIntegerOverflowFlags ();
2330
+ builder->setIntegerOverflowFlags (
2331
+ mlir::arith::IntegerOverflowFlags::nsw);
2332
+ }
2320
2333
2321
- info.loopVariable = genLoopVariableAddress (loc, *info.loopVariableSym ,
2322
- info.isUnordered );
2323
- if (!getLoweringOptions ().getIntegerWrapAround ()) {
2324
- iofBackup = builder->getIntegerOverflowFlags ();
2325
- builder->setIntegerOverflowFlags (
2326
- mlir::arith::IntegerOverflowFlags::nsw);
2327
- }
2328
- lowerValue = genControlValue (info.lowerExpr , info);
2329
- upperValue = genControlValue (info.upperExpr , info);
2330
- bool isConst = true ;
2331
- stepValue = genControlValue (info.stepExpr , info,
2332
- info.isStructured () ? nullptr : &isConst);
2333
- if (!getLoweringOptions ().getIntegerWrapAround ())
2334
- builder->setIntegerOverflowFlags (iofBackup);
2335
- boundsAndStepIP = stepValue.getDefiningOp ();
2336
-
2337
- // Use a temp variable for unstructured loops with non-const step.
2338
- if (!isConst) {
2339
- info.stepVariable =
2340
- builder->createTemporary (loc, stepValue.getType ());
2341
- boundsAndStepIP =
2342
- builder->create <fir::StoreOp>(loc, stepValue, info.stepVariable );
2334
+ nestLBs.push_back (genControlValue (info.lowerExpr , info));
2335
+ nestUBs.push_back (genControlValue (info.upperExpr , info));
2336
+ bool isConst = true ;
2337
+ nestSts.push_back (genControlValue (
2338
+ info.stepExpr , info, info.isStructured () ? nullptr : &isConst));
2339
+
2340
+ if (!getLoweringOptions ().getIntegerWrapAround ())
2341
+ builder->setIntegerOverflowFlags (iofBackup);
2342
+
2343
+ // Use a temp variable for unstructured loops with non-const step.
2344
+ if (!isConst) {
2345
+ mlir::Value stepValue = nestSts.back ();
2346
+ info.stepVariable = builder->createTemporary (loc, stepValue.getType ());
2347
+ builder->create <fir::StoreOp>(loc, stepValue, info.stepVariable );
2348
+ }
2349
+
2350
+ if (genDoConcurrent && nestReduceOperands.empty ()) {
2351
+ // Create DO CONCURRENT reduce operands and attributes
2352
+ for (const auto &reduceSym : info.reduceSymList ) {
2353
+ const fir::ReduceOperationEnum reduceOperation = reduceSym.first ;
2354
+ const Fortran::semantics::Symbol *sym = reduceSym.second ;
2355
+ fir::ExtendedValue exv = getSymbolExtendedValue (*sym, nullptr );
2356
+ nestReduceOperands.push_back (fir::getBase (exv));
2357
+ auto reduceAttr =
2358
+ fir::ReduceAttr::get (builder->getContext (), reduceOperation);
2359
+ nestReduceAttrs.push_back (reduceAttr);
2343
2360
}
2344
2361
}
2362
+ }
2345
2363
2364
+ for (auto [info, lowerValue, upperValue, stepValue] :
2365
+ llvm::zip_equal (incrementLoopNestInfo, nestLBs, nestUBs, nestSts)) {
2346
2366
// Structured loop - generate fir.do_loop.
2347
2367
if (info.isStructured ()) {
2368
+ if (genDoConcurrent)
2369
+ continue ;
2370
+
2371
+ // The loop variable is a doLoop op argument.
2348
2372
mlir::Type loopVarType = info.getLoopVariableType ();
2349
- mlir::Value loopValue;
2350
- if (info.isUnordered ) {
2351
- llvm::SmallVector<mlir::Value> reduceOperands;
2352
- llvm::SmallVector<mlir::Attribute> reduceAttrs;
2353
- // Create DO CONCURRENT reduce operands and attributes
2354
- for (const auto &reduceSym : info.reduceSymList ) {
2355
- const fir::ReduceOperationEnum reduce_operation = reduceSym.first ;
2356
- const Fortran::semantics::Symbol *sym = reduceSym.second ;
2357
- fir::ExtendedValue exv = getSymbolExtendedValue (*sym, nullptr );
2358
- reduceOperands.push_back (fir::getBase (exv));
2359
- auto reduce_attr =
2360
- fir::ReduceAttr::get (builder->getContext (), reduce_operation);
2361
- reduceAttrs.push_back (reduce_attr);
2362
- }
2363
- // The loop variable value is explicitly updated.
2364
- info.doLoop = builder->create <fir::DoLoopOp>(
2365
- loc, lowerValue, upperValue, stepValue, /* unordered=*/ true ,
2366
- /* finalCountValue=*/ false , /* iterArgs=*/ std::nullopt,
2367
- llvm::ArrayRef<mlir::Value>(reduceOperands), reduceAttrs);
2368
- builder->setInsertionPointToStart (info.doLoop .getBody ());
2369
- loopValue = builder->createConvert (loc, loopVarType,
2370
- info.doLoop .getInductionVar ());
2371
- } else {
2372
- // The loop variable is a doLoop op argument.
2373
- info.doLoop = builder->create <fir::DoLoopOp>(
2374
- loc, lowerValue, upperValue, stepValue, /* unordered=*/ false ,
2375
- /* finalCountValue=*/ true ,
2376
- builder->createConvert (loc, loopVarType, lowerValue));
2377
- builder->setInsertionPointToStart (info.doLoop .getBody ());
2378
- loopValue = info.doLoop .getRegionIterArgs ()[0 ];
2379
- }
2373
+ auto loopOp = builder->create <fir::DoLoopOp>(
2374
+ loc, lowerValue, upperValue, stepValue, /* unordered=*/ false ,
2375
+ /* finalCountValue=*/ true ,
2376
+ builder->createConvert (loc, loopVarType, lowerValue));
2377
+ info.loopOp = loopOp;
2378
+ builder->setInsertionPointToStart (loopOp.getBody ());
2379
+ mlir::Value loopValue = loopOp.getRegionIterArgs ()[0 ];
2380
+
2380
2381
// Update the loop variable value in case it has non-index references.
2381
2382
builder->create <fir::StoreOp>(loc, loopValue, info.loopVariable );
2382
- if (info.maskExpr ) {
2383
- Fortran::lower::StatementContext stmtCtx;
2384
- mlir::Value maskCond = createFIRExpr (loc, info.maskExpr , stmtCtx);
2385
- stmtCtx.finalizeAndReset ();
2386
- mlir::Value maskCondCast =
2387
- builder->createConvert (loc, builder->getI1Type (), maskCond);
2388
- auto ifOp = builder->create <fir::IfOp>(loc, maskCondCast,
2389
- /* withElseRegion=*/ false );
2390
- builder->setInsertionPointToStart (&ifOp.getThenRegion ().front ());
2391
- }
2392
- if (info.hasLocalitySpecs ())
2393
- handleLocalitySpecs (info);
2394
-
2395
2383
addLoopAnnotationAttr (info, dirs);
2396
2384
continue ;
2397
2385
}
@@ -2455,6 +2443,60 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2455
2443
builder->restoreInsertionPoint (insertPt);
2456
2444
}
2457
2445
}
2446
+
2447
+ if (genDoConcurrent) {
2448
+ auto loopWrapperOp = builder->create <fir::DoConcurrentOp>(loc);
2449
+ builder->setInsertionPointToStart (
2450
+ builder->createBlock (&loopWrapperOp.getRegion ()));
2451
+
2452
+ for (IncrementLoopInfo &info : llvm::reverse (incrementLoopNestInfo)) {
2453
+ info.loopVariable = genLoopVariableAddress (loc, *info.loopVariableSym ,
2454
+ info.isConcurrent );
2455
+ }
2456
+
2457
+ builder->setInsertionPointToEnd (loopWrapperOp.getBody ());
2458
+ auto loopOp = builder->create <fir::DoConcurrentLoopOp>(
2459
+ loc, nestLBs, nestUBs, nestSts, nestReduceOperands,
2460
+ nestReduceAttrs.empty ()
2461
+ ? nullptr
2462
+ : mlir::ArrayAttr::get (builder->getContext (), nestReduceAttrs),
2463
+ nullptr );
2464
+
2465
+ llvm::SmallVector<mlir::Type> loopBlockArgTypes (
2466
+ incrementLoopNestInfo.size (), builder->getIndexType ());
2467
+ llvm::SmallVector<mlir::Location> loopBlockArgLocs (
2468
+ incrementLoopNestInfo.size (), loc);
2469
+ mlir::Region &loopRegion = loopOp.getRegion ();
2470
+ mlir::Block *loopBlock = builder->createBlock (
2471
+ &loopRegion, loopRegion.begin (), loopBlockArgTypes, loopBlockArgLocs);
2472
+ builder->setInsertionPointToStart (loopBlock);
2473
+
2474
+ for (auto [info, blockArg] :
2475
+ llvm::zip_equal (incrementLoopNestInfo, loopBlock->getArguments ())) {
2476
+ info.loopOp = loopOp;
2477
+ mlir::Value loopValue =
2478
+ builder->createConvert (loc, info.getLoopVariableType (), blockArg);
2479
+ builder->create <fir::StoreOp>(loc, loopValue, info.loopVariable );
2480
+
2481
+ if (info.maskExpr ) {
2482
+ Fortran::lower::StatementContext stmtCtx;
2483
+ mlir::Value maskCond = createFIRExpr (loc, info.maskExpr , stmtCtx);
2484
+ stmtCtx.finalizeAndReset ();
2485
+ mlir::Value maskCondCast =
2486
+ builder->createConvert (loc, builder->getI1Type (), maskCond);
2487
+ auto ifOp = builder->create <fir::IfOp>(loc, maskCondCast,
2488
+ /* withElseRegion=*/ false );
2489
+ builder->setInsertionPointToStart (&ifOp.getThenRegion ().front ());
2490
+ }
2491
+ }
2492
+
2493
+ IncrementLoopInfo &innermostInfo = incrementLoopNestInfo.back ();
2494
+
2495
+ if (innermostInfo.hasLocalitySpecs ())
2496
+ handleLocalitySpecs (innermostInfo);
2497
+
2498
+ addLoopAnnotationAttr (innermostInfo, dirs);
2499
+ }
2458
2500
}
2459
2501
2460
2502
// / Generate FIR to end a structured or unstructured increment loop nest.
@@ -2471,29 +2513,31 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2471
2513
it != rend; ++it) {
2472
2514
IncrementLoopInfo &info = *it;
2473
2515
if (info.isStructured ()) {
2474
- // End fir.do_loop .
2475
- if (info.isUnordered ) {
2476
- builder->setInsertionPointAfter (info.doLoop );
2516
+ // End fir.do_concurent.loop .
2517
+ if (info.isConcurrent ) {
2518
+ builder->setInsertionPointAfter (info.loopOp -> getParentOp () );
2477
2519
continue ;
2478
2520
}
2521
+
2522
+ // End fir.do_loop.
2479
2523
// Decrement tripVariable.
2480
- builder->setInsertionPointToEnd (info.doLoop .getBody ());
2524
+ auto doLoopOp = mlir::cast<fir::DoLoopOp>(info.loopOp );
2525
+ builder->setInsertionPointToEnd (doLoopOp.getBody ());
2481
2526
llvm::SmallVector<mlir::Value, 2 > results;
2482
2527
results.push_back (builder->create <mlir::arith::AddIOp>(
2483
- loc, info.doLoop .getInductionVar (), info.doLoop .getStep (),
2484
- iofAttr));
2528
+ loc, doLoopOp.getInductionVar (), doLoopOp.getStep (), iofAttr));
2485
2529
// Step loopVariable to help optimizations such as vectorization.
2486
2530
// Induction variable elimination will clean up as necessary.
2487
2531
mlir::Value step = builder->createConvert (
2488
- loc, info.getLoopVariableType (), info. doLoop .getStep ());
2532
+ loc, info.getLoopVariableType (), doLoopOp .getStep ());
2489
2533
mlir::Value loopVar =
2490
2534
builder->create <fir::LoadOp>(loc, info.loopVariable );
2491
2535
results.push_back (
2492
2536
builder->create <mlir::arith::AddIOp>(loc, loopVar, step, iofAttr));
2493
2537
builder->create <fir::ResultOp>(loc, results);
2494
- builder->setInsertionPointAfter (info. doLoop );
2538
+ builder->setInsertionPointAfter (doLoopOp );
2495
2539
// The loop control variable may be used after the loop.
2496
- builder->create <fir::StoreOp>(loc, info. doLoop .getResult (1 ),
2540
+ builder->create <fir::StoreOp>(loc, doLoopOp .getResult (1 ),
2497
2541
info.loopVariable );
2498
2542
continue ;
2499
2543
}
0 commit comments