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