@@ -130,7 +130,7 @@ struct IncrementLoopInfo {
130130 mlir::Value loopVariable = nullptr ;
131131
132132 // Data members for structured loops.
133- fir::DoLoopOp doLoop = nullptr ;
133+ mlir::Operation *loopOp = nullptr ;
134134
135135 // Data members for unstructured loops.
136136 bool hasRealControl = false ;
@@ -2267,8 +2267,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
22672267 mlir::LLVM::LoopAnnotationAttr la = mlir::LLVM::LoopAnnotationAttr::get (
22682268 builder->getContext (), {}, /* vectorize=*/ va, {}, /* unroll*/ ua,
22692269 /* 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+ }
22722278 }
22732279
22742280 // / Generate FIR to begin a structured or unstructured increment loop nest.
@@ -2277,96 +2283,77 @@ class FirConverter : public Fortran::lower::AbstractConverter {
22772283 llvm::SmallVectorImpl<const Fortran::parser::CompilerDirective *> &dirs) {
22782284 assert (!incrementLoopNestInfo.empty () && " empty loop nest" );
22792285 mlir::Location loc = toLocation ();
2280- mlir::Operation *boundsAndStepIP = nullptr ;
22812286 mlir::arith::IntegerOverflowFlags iofBackup{};
22822287
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 ;
22902294
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 ;
22952297
2298+ if (!genDoConcurrent)
22962299 info.loopVariable = genLoopVariableAddress (loc, *info.loopVariableSym ,
22972300 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);
23182334 }
23192335 }
2336+ }
23202337
2338+ for (auto [info, lowerValue, upperValue, stepValue] :
2339+ llvm::zip_equal (incrementLoopNestInfo, nestLBs, nestUBs, nestSts)) {
23212340 // Structured loop - generate fir.do_loop.
23222341 if (info.isStructured ()) {
2342+ if (info.isUnordered )
2343+ continue ;
2344+
2345+ // The loop variable is a doLoop op argument.
23232346 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+
23552355 // Update the loop variable value in case it has non-index references.
23562356 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-
23702357 addLoopAnnotationAttr (info, dirs);
23712358 continue ;
23722359 }
@@ -2430,6 +2417,60 @@ class FirConverter : public Fortran::lower::AbstractConverter {
24302417 builder->restoreInsertionPoint (insertPt);
24312418 }
24322419 }
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+ }
24332474 }
24342475
24352476 // / Generate FIR to end a structured or unstructured increment loop nest.
@@ -2446,29 +2487,31 @@ class FirConverter : public Fortran::lower::AbstractConverter {
24462487 it != rend; ++it) {
24472488 IncrementLoopInfo &info = *it;
24482489 if (info.isStructured ()) {
2449- // End fir.do_loop .
2490+ // End fir.do_concurent.loop .
24502491 if (info.isUnordered ) {
2451- builder->setInsertionPointAfter (info.doLoop );
2492+ builder->setInsertionPointAfter (info.loopOp -> getParentOp () );
24522493 continue ;
24532494 }
2495+
2496+ // End fir.do_loop.
24542497 // Decrement tripVariable.
2455- builder->setInsertionPointToEnd (info.doLoop .getBody ());
2498+ auto doLoopOp = mlir::cast<fir::DoLoopOp>(info.loopOp );
2499+ builder->setInsertionPointToEnd (doLoopOp.getBody ());
24562500 llvm::SmallVector<mlir::Value, 2 > results;
24572501 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));
24602503 // Step loopVariable to help optimizations such as vectorization.
24612504 // Induction variable elimination will clean up as necessary.
24622505 mlir::Value step = builder->createConvert (
2463- loc, info.getLoopVariableType (), info. doLoop .getStep ());
2506+ loc, info.getLoopVariableType (), doLoopOp .getStep ());
24642507 mlir::Value loopVar =
24652508 builder->create <fir::LoadOp>(loc, info.loopVariable );
24662509 results.push_back (
24672510 builder->create <mlir::arith::AddIOp>(loc, loopVar, step, iofAttr));
24682511 builder->create <fir::ResultOp>(loc, results);
2469- builder->setInsertionPointAfter (info. doLoop );
2512+ builder->setInsertionPointAfter (doLoopOp );
24702513 // 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 ),
24722515 info.loopVariable );
24732516 continue ;
24742517 }
0 commit comments