@@ -130,7 +130,7 @@ struct IncrementLoopInfo {
130
130
mlir::Value loopVariable = nullptr ;
131
131
132
132
// Data members for structured loops.
133
- fir::DoLoopOp doLoop = nullptr ;
133
+ mlir::Operation *loopOp = nullptr ;
134
134
135
135
// Data members for unstructured loops.
136
136
bool hasRealControl = false ;
@@ -2267,8 +2267,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2267
2267
mlir::LLVM::LoopAnnotationAttr la = mlir::LLVM::LoopAnnotationAttr::get (
2268
2268
builder->getContext (), {}, /* vectorize=*/ va, {}, /* unroll*/ ua,
2269
2269
/* unroll_and_jam*/ uja, {}, {}, {}, {}, {}, {}, {}, {}, {}, {});
2270
- if (has_attrs)
2271
- info.doLoop .setLoopAnnotationAttr (la);
2270
+ if (has_attrs) {
2271
+ if (auto loopOp = mlir::dyn_cast<fir::DoLoopOp>(info.loopOp ))
2272
+ loopOp.setLoopAnnotationAttr (la);
2273
+
2274
+ if (auto doConcurrentOp =
2275
+ mlir::dyn_cast<fir::DoConcurrentLoopOp>(info.loopOp ))
2276
+ doConcurrentOp.setLoopAnnotationAttr (la);
2277
+ }
2272
2278
}
2273
2279
2274
2280
// / Generate FIR to begin a structured or unstructured increment loop nest.
@@ -2277,96 +2283,77 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2277
2283
llvm::SmallVectorImpl<const Fortran::parser::CompilerDirective *> &dirs) {
2278
2284
assert (!incrementLoopNestInfo.empty () && " empty loop nest" );
2279
2285
mlir::Location loc = toLocation ();
2280
- mlir::Operation *boundsAndStepIP = nullptr ;
2281
2286
mlir::arith::IntegerOverflowFlags iofBackup{};
2282
2287
2283
- for (IncrementLoopInfo &info : incrementLoopNestInfo) {
2284
- mlir::Value lowerValue;
2285
- mlir::Value upperValue;
2286
- mlir::Value stepValue;
2287
-
2288
- {
2289
- mlir::OpBuilder::InsertionGuard guard (*builder);
2288
+ llvm::SmallVector<mlir::Value> nestLBs;
2289
+ llvm::SmallVector<mlir::Value> nestUBs;
2290
+ llvm::SmallVector<mlir::Value> nestSts;
2291
+ llvm::SmallVector<mlir::Value> nestReduceOperands;
2292
+ llvm::SmallVector<mlir::Attribute> nestReduceAttrs;
2293
+ bool genDoConcurrent = false ;
2290
2294
2291
- // Set the IP before the first loop in the nest so that all nest bounds
2292
- // and step values are created outside the nest.
2293
- if (boundsAndStepIP)
2294
- builder->setInsertionPointAfter (boundsAndStepIP);
2295
+ for (IncrementLoopInfo &info : incrementLoopNestInfo) {
2296
+ genDoConcurrent = info.isStructured () && info.isUnordered ;
2295
2297
2298
+ if (!genDoConcurrent)
2296
2299
info.loopVariable = genLoopVariableAddress (loc, *info.loopVariableSym ,
2297
2300
info.isUnordered );
2298
- if (!getLoweringOptions ().getIntegerWrapAround ()) {
2299
- iofBackup = builder->getIntegerOverflowFlags ();
2300
- builder->setIntegerOverflowFlags (
2301
- mlir::arith::IntegerOverflowFlags::nsw);
2302
- }
2303
- lowerValue = genControlValue (info.lowerExpr , info);
2304
- upperValue = genControlValue (info.upperExpr , info);
2305
- bool isConst = true ;
2306
- stepValue = genControlValue (info.stepExpr , info,
2307
- info.isStructured () ? nullptr : &isConst);
2308
- if (!getLoweringOptions ().getIntegerWrapAround ())
2309
- builder->setIntegerOverflowFlags (iofBackup);
2310
- boundsAndStepIP = stepValue.getDefiningOp ();
2311
-
2312
- // Use a temp variable for unstructured loops with non-const step.
2313
- if (!isConst) {
2314
- info.stepVariable =
2315
- builder->createTemporary (loc, stepValue.getType ());
2316
- boundsAndStepIP =
2317
- builder->create <fir::StoreOp>(loc, stepValue, info.stepVariable );
2301
+
2302
+ if (!getLoweringOptions ().getIntegerWrapAround ()) {
2303
+ iofBackup = builder->getIntegerOverflowFlags ();
2304
+ builder->setIntegerOverflowFlags (
2305
+ mlir::arith::IntegerOverflowFlags::nsw);
2306
+ }
2307
+
2308
+ nestLBs.push_back (genControlValue (info.lowerExpr , info));
2309
+ nestUBs.push_back (genControlValue (info.upperExpr , info));
2310
+ bool isConst = true ;
2311
+ nestSts.push_back (genControlValue (
2312
+ info.stepExpr , info, info.isStructured () ? nullptr : &isConst));
2313
+
2314
+ if (!getLoweringOptions ().getIntegerWrapAround ())
2315
+ builder->setIntegerOverflowFlags (iofBackup);
2316
+
2317
+ // Use a temp variable for unstructured loops with non-const step.
2318
+ if (!isConst) {
2319
+ mlir::Value stepValue = nestSts.back ();
2320
+ info.stepVariable = builder->createTemporary (loc, stepValue.getType ());
2321
+ builder->create <fir::StoreOp>(loc, stepValue, info.stepVariable );
2322
+ }
2323
+
2324
+ if (genDoConcurrent && nestReduceOperands.empty ()) {
2325
+ // Create DO CONCURRENT reduce operands and attributes
2326
+ for (const auto &reduceSym : info.reduceSymList ) {
2327
+ const fir::ReduceOperationEnum reduceOperation = reduceSym.first ;
2328
+ const Fortran::semantics::Symbol *sym = reduceSym.second ;
2329
+ fir::ExtendedValue exv = getSymbolExtendedValue (*sym, nullptr );
2330
+ nestReduceOperands.push_back (fir::getBase (exv));
2331
+ auto reduceAttr =
2332
+ fir::ReduceAttr::get (builder->getContext (), reduceOperation);
2333
+ nestReduceAttrs.push_back (reduceAttr);
2318
2334
}
2319
2335
}
2336
+ }
2320
2337
2338
+ for (auto [info, lowerValue, upperValue, stepValue] :
2339
+ llvm::zip_equal (incrementLoopNestInfo, nestLBs, nestUBs, nestSts)) {
2321
2340
// Structured loop - generate fir.do_loop.
2322
2341
if (info.isStructured ()) {
2342
+ if (info.isUnordered )
2343
+ continue ;
2344
+
2345
+ // The loop variable is a doLoop op argument.
2323
2346
mlir::Type loopVarType = info.getLoopVariableType ();
2324
- mlir::Value loopValue;
2325
- if (info.isUnordered ) {
2326
- llvm::SmallVector<mlir::Value> reduceOperands;
2327
- llvm::SmallVector<mlir::Attribute> reduceAttrs;
2328
- // Create DO CONCURRENT reduce operands and attributes
2329
- for (const auto &reduceSym : info.reduceSymList ) {
2330
- const fir::ReduceOperationEnum reduce_operation = reduceSym.first ;
2331
- const Fortran::semantics::Symbol *sym = reduceSym.second ;
2332
- fir::ExtendedValue exv = getSymbolExtendedValue (*sym, nullptr );
2333
- reduceOperands.push_back (fir::getBase (exv));
2334
- auto reduce_attr =
2335
- fir::ReduceAttr::get (builder->getContext (), reduce_operation);
2336
- reduceAttrs.push_back (reduce_attr);
2337
- }
2338
- // The loop variable value is explicitly updated.
2339
- info.doLoop = builder->create <fir::DoLoopOp>(
2340
- loc, lowerValue, upperValue, stepValue, /* unordered=*/ true ,
2341
- /* finalCountValue=*/ false , /* iterArgs=*/ std::nullopt,
2342
- llvm::ArrayRef<mlir::Value>(reduceOperands), reduceAttrs);
2343
- builder->setInsertionPointToStart (info.doLoop .getBody ());
2344
- loopValue = builder->createConvert (loc, loopVarType,
2345
- info.doLoop .getInductionVar ());
2346
- } else {
2347
- // The loop variable is a doLoop op argument.
2348
- info.doLoop = builder->create <fir::DoLoopOp>(
2349
- loc, lowerValue, upperValue, stepValue, /* unordered=*/ false ,
2350
- /* finalCountValue=*/ true ,
2351
- builder->createConvert (loc, loopVarType, lowerValue));
2352
- builder->setInsertionPointToStart (info.doLoop .getBody ());
2353
- loopValue = info.doLoop .getRegionIterArgs ()[0 ];
2354
- }
2347
+ auto loopOp = builder->create <fir::DoLoopOp>(
2348
+ loc, lowerValue, upperValue, stepValue, /* unordered=*/ false ,
2349
+ /* finalCountValue=*/ true ,
2350
+ builder->createConvert (loc, loopVarType, lowerValue));
2351
+ info.loopOp = loopOp;
2352
+ builder->setInsertionPointToStart (loopOp.getBody ());
2353
+ mlir::Value loopValue = loopOp.getRegionIterArgs ()[0 ];
2354
+
2355
2355
// Update the loop variable value in case it has non-index references.
2356
2356
builder->create <fir::StoreOp>(loc, loopValue, info.loopVariable );
2357
- if (info.maskExpr ) {
2358
- Fortran::lower::StatementContext stmtCtx;
2359
- mlir::Value maskCond = createFIRExpr (loc, info.maskExpr , stmtCtx);
2360
- stmtCtx.finalizeAndReset ();
2361
- mlir::Value maskCondCast =
2362
- builder->createConvert (loc, builder->getI1Type (), maskCond);
2363
- auto ifOp = builder->create <fir::IfOp>(loc, maskCondCast,
2364
- /* withElseRegion=*/ false );
2365
- builder->setInsertionPointToStart (&ifOp.getThenRegion ().front ());
2366
- }
2367
- if (info.hasLocalitySpecs ())
2368
- handleLocalitySpecs (info);
2369
-
2370
2357
addLoopAnnotationAttr (info, dirs);
2371
2358
continue ;
2372
2359
}
@@ -2430,6 +2417,60 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2430
2417
builder->restoreInsertionPoint (insertPt);
2431
2418
}
2432
2419
}
2420
+
2421
+ if (genDoConcurrent) {
2422
+ auto loopWrapperOp = builder->create <fir::DoConcurrentOp>(loc);
2423
+ builder->setInsertionPointToStart (
2424
+ builder->createBlock (&loopWrapperOp.getRegion ()));
2425
+
2426
+ for (IncrementLoopInfo &info : llvm::reverse (incrementLoopNestInfo)) {
2427
+ info.loopVariable = genLoopVariableAddress (loc, *info.loopVariableSym ,
2428
+ info.isUnordered );
2429
+ }
2430
+
2431
+ builder->setInsertionPointToEnd (loopWrapperOp.getBody ());
2432
+ auto loopOp = builder->create <fir::DoConcurrentLoopOp>(
2433
+ loc, nestLBs, nestUBs, nestSts, nestReduceOperands,
2434
+ nestReduceAttrs.empty ()
2435
+ ? nullptr
2436
+ : mlir::ArrayAttr::get (builder->getContext (), nestReduceAttrs),
2437
+ nullptr );
2438
+
2439
+ llvm::SmallVector<mlir::Type> loopBlockArgTypes (
2440
+ incrementLoopNestInfo.size (), builder->getIndexType ());
2441
+ llvm::SmallVector<mlir::Location> loopBlockArgLocs (
2442
+ incrementLoopNestInfo.size (), loc);
2443
+ mlir::Region &loopRegion = loopOp.getRegion ();
2444
+ mlir::Block *loopBlock = builder->createBlock (
2445
+ &loopRegion, loopRegion.begin (), loopBlockArgTypes, loopBlockArgLocs);
2446
+ builder->setInsertionPointToStart (loopBlock);
2447
+
2448
+ for (auto [info, blockArg] :
2449
+ llvm::zip_equal (incrementLoopNestInfo, loopBlock->getArguments ())) {
2450
+ info.loopOp = loopOp;
2451
+ mlir::Value loopValue =
2452
+ builder->createConvert (loc, info.getLoopVariableType (), blockArg);
2453
+ builder->create <fir::StoreOp>(loc, loopValue, info.loopVariable );
2454
+
2455
+ if (info.maskExpr ) {
2456
+ Fortran::lower::StatementContext stmtCtx;
2457
+ mlir::Value maskCond = createFIRExpr (loc, info.maskExpr , stmtCtx);
2458
+ stmtCtx.finalizeAndReset ();
2459
+ mlir::Value maskCondCast =
2460
+ builder->createConvert (loc, builder->getI1Type (), maskCond);
2461
+ auto ifOp = builder->create <fir::IfOp>(loc, maskCondCast,
2462
+ /* withElseRegion=*/ false );
2463
+ builder->setInsertionPointToStart (&ifOp.getThenRegion ().front ());
2464
+ }
2465
+ }
2466
+
2467
+ IncrementLoopInfo &innermostInfo = incrementLoopNestInfo.back ();
2468
+
2469
+ if (innermostInfo.hasLocalitySpecs ())
2470
+ handleLocalitySpecs (innermostInfo);
2471
+
2472
+ addLoopAnnotationAttr (innermostInfo, dirs);
2473
+ }
2433
2474
}
2434
2475
2435
2476
// / Generate FIR to end a structured or unstructured increment loop nest.
@@ -2446,29 +2487,31 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2446
2487
it != rend; ++it) {
2447
2488
IncrementLoopInfo &info = *it;
2448
2489
if (info.isStructured ()) {
2449
- // End fir.do_loop .
2490
+ // End fir.do_concurent.loop .
2450
2491
if (info.isUnordered ) {
2451
- builder->setInsertionPointAfter (info.doLoop );
2492
+ builder->setInsertionPointAfter (info.loopOp -> getParentOp () );
2452
2493
continue ;
2453
2494
}
2495
+
2496
+ // End fir.do_loop.
2454
2497
// Decrement tripVariable.
2455
- builder->setInsertionPointToEnd (info.doLoop .getBody ());
2498
+ auto doLoopOp = mlir::cast<fir::DoLoopOp>(info.loopOp );
2499
+ builder->setInsertionPointToEnd (doLoopOp.getBody ());
2456
2500
llvm::SmallVector<mlir::Value, 2 > results;
2457
2501
results.push_back (builder->create <mlir::arith::AddIOp>(
2458
- loc, info.doLoop .getInductionVar (), info.doLoop .getStep (),
2459
- iofAttr));
2502
+ loc, doLoopOp.getInductionVar (), doLoopOp.getStep (), iofAttr));
2460
2503
// Step loopVariable to help optimizations such as vectorization.
2461
2504
// Induction variable elimination will clean up as necessary.
2462
2505
mlir::Value step = builder->createConvert (
2463
- loc, info.getLoopVariableType (), info. doLoop .getStep ());
2506
+ loc, info.getLoopVariableType (), doLoopOp .getStep ());
2464
2507
mlir::Value loopVar =
2465
2508
builder->create <fir::LoadOp>(loc, info.loopVariable );
2466
2509
results.push_back (
2467
2510
builder->create <mlir::arith::AddIOp>(loc, loopVar, step, iofAttr));
2468
2511
builder->create <fir::ResultOp>(loc, results);
2469
- builder->setInsertionPointAfter (info. doLoop );
2512
+ builder->setInsertionPointAfter (doLoopOp );
2470
2513
// The loop control variable may be used after the loop.
2471
- builder->create <fir::StoreOp>(loc, info. doLoop .getResult (1 ),
2514
+ builder->create <fir::StoreOp>(loc, doLoopOp .getResult (1 ),
2472
2515
info.loopVariable );
2473
2516
continue ;
2474
2517
}
0 commit comments