@@ -2326,12 +2326,50 @@ genParallelOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
23262326
23272327static mlir::omp::ScanOp
23282328genScanOp (lower::AbstractConverter &converter, lower::SymMap &symTable,
2329- semantics::SemanticsContext &semaCtx, mlir::Location loc,
2330- const ConstructQueue &queue, ConstructQueue::const_iterator item) {
2329+ semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
2330+ mlir::Location loc, const ConstructQueue &queue,
2331+ ConstructQueue::const_iterator item) {
23312332 mlir::omp::ScanOperands clauseOps;
23322333 genScanClauses (converter, semaCtx, item->clauses , loc, clauseOps);
2333- return mlir::omp::ScanOp::create (converter.getFirOpBuilder (),
2334- converter.getCurrentLocation (), clauseOps);
2334+ mlir::omp::ScanOp scanOp = mlir::omp::ScanOp::create (
2335+ converter.getFirOpBuilder (), converter.getCurrentLocation (), clauseOps);
2336+
2337+ // / Scan redution is not implemented with nested workshare loops, linear clause, tiling
2338+ mlir::omp::LoopNestOp loopNestOp =
2339+ scanOp->getParentOfType <mlir::omp::LoopNestOp>();
2340+ mlir::omp::WsloopOp wsLoopOp =
2341+ scanOp->getParentOfType <mlir::omp::WsloopOp>();
2342+ bool isNested = (loopNestOp.getNumLoops () > 1 ) || (wsLoopOp && (wsLoopOp->getParentOfType <mlir::omp::WsloopOp>()));
2343+ if (isNested)
2344+ TODO (loc, " Scan directive inside nested workshare loops" );
2345+ if (wsLoopOp && !wsLoopOp.getLinearVars ().empty ())
2346+ TODO (loc, " Scan directive with linear clause" );
2347+ if (loopNestOp.getTileSizes ())
2348+ TODO (loc, " Scan directive with loop tiling" );
2349+
2350+ // All loop indices should be loaded after the scan construct as otherwise,
2351+ // it would result in using the index variable across scan directive.
2352+ // (`Intra-iteration dependences from a statement in the structured
2353+ // block sequence that precede a scan directive to a statement in the
2354+ // structured block sequence that follows a scan directive must not exist,
2355+ // except for dependences for the list items specified in an inclusive or
2356+ // exclusive clause.`).
2357+ // TODO: Nested loops are not handled.
2358+ mlir::Region ®ion = loopNestOp->getRegion (0 );
2359+ mlir::Value indexVal = fir::getBase (region.getArgument (0 ));
2360+ lower::pft::Evaluation *doConstructEval = eval.parentConstruct ;
2361+ fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
2362+ lower::pft::Evaluation *doLoop = &doConstructEval->getFirstNestedEvaluation ();
2363+ auto *doStmt = doLoop->getIf <parser::NonLabelDoStmt>();
2364+ assert (doStmt && " Expected do loop to be in the nested evaluation" );
2365+ const auto &loopControl =
2366+ std::get<std::optional<parser::LoopControl>>(doStmt->t );
2367+ const parser::LoopControl::Bounds *bounds =
2368+ std::get_if<parser::LoopControl::Bounds>(&loopControl->u );
2369+ mlir::Operation *storeOp =
2370+ setLoopVar (converter, loc, indexVal, bounds->name .thing .symbol );
2371+ firOpBuilder.setInsertionPointAfter (storeOp);
2372+ return scanOp;
23352373}
23362374
23372375static mlir::omp::SectionsOp
@@ -3416,7 +3454,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
34163454 loc, queue, item);
34173455 break ;
34183456 case llvm::omp::Directive::OMPD_scan:
3419- newOp = genScanOp (converter, symTable, semaCtx, loc, queue, item);
3457+ newOp = genScanOp (converter, symTable, semaCtx, eval, loc, queue, item);
34203458 break ;
34213459 case llvm::omp::Directive::OMPD_section:
34223460 llvm_unreachable (" genOMPDispatch: OMPD_section" );
0 commit comments