Index: flang/lib/Lower/OpenMP.cpp =================================================================== --- flang/lib/Lower/OpenMP.cpp +++ flang/lib/Lower/OpenMP.cpp @@ -24,6 +24,9 @@ #include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" +using OmpClauseSet = + Fortran::common::EnumSet; + using namespace mlir; int64_t Fortran::lower::getCollapseValue( @@ -80,18 +83,21 @@ } static void privatizeVars(Fortran::lower::AbstractConverter &converter, - const Fortran::parser::OmpClauseList &opClauseList) { + const Fortran::parser::OmpClauseList &opClauseList, + const OmpClauseSet &set) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); auto insPt = firOpBuilder.saveInsertionPoint(); firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); for (const Fortran::parser::OmpClause &clause : opClauseList.v) { if (const auto &privateClause = std::get_if(&clause.u)) { - createPrivateVarSyms(converter, privateClause); + if (set.test(llvm::omp::Clause::OMPC_private)) + createPrivateVarSyms(converter, privateClause); } else if (const auto &firstPrivateClause = std::get_if( &clause.u)) { - createPrivateVarSyms(converter, firstPrivateClause); + if (set.test(llvm::omp::Clause::OMPC_firstprivate)) + createPrivateVarSyms(converter, firstPrivateClause); } } firOpBuilder.restoreInsertionPoint(insPt); @@ -256,7 +262,8 @@ } } -/// Create the body (block) for an OpenMP Operation. +/// Create the body (block) for an OpenMP Operation, which is an non-combined +/// construct or one part of combined construct. /// /// \param [in] op - the operation the body belongs to. /// \param [inout] converter - converter to use for the clauses. @@ -267,13 +274,14 @@ //// region. /// \param [in] outerCombined - is this an outer operation - prevents /// privatization. +/// \param [in] set - set of clauses to be implemented in this \p op. template static void createBodyOfOp(Op &op, Fortran::lower::AbstractConverter &converter, mlir::Location &loc, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OmpClauseList *clauses = nullptr, const SmallVector &args = {}, - bool outerCombined = false) { + bool outerCombined = false, const OmpClauseSet &set = {}) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); // If an argument for the region is provided then create the block with that // argument. Also update the symbol's address with the mlir argument value. @@ -335,9 +343,11 @@ else firOpBuilder.setInsertionPointToStart(&block); - // Handle privatization. Do not privatize if this is the outer operation. - if (clauses && !outerCombined) - privatizeVars(converter, *clauses); + // Handle privatization. + if (clauses && !set.empty() && + (set.test(llvm::omp::Clause::OMPC_private) || + set.test(llvm::omp::Clause::OMPC_firstprivate))) + privatizeVars(converter, *clauses, set); if (std::is_same_v) threadPrivatizeVars(converter, eval); @@ -474,7 +484,8 @@ static void createCombinedParallelOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, - const Directive &directive) { + const Directive &directive, + const OmpClauseSet &set = {}) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Location currentLocation = converter.getCurrentLocation(); Fortran::lower::StatementContext stmtCtx; @@ -598,6 +609,8 @@ nowaitAttr = firOpBuilder.getUnitAttr(); } + OmpClauseSet privatizeSet{llvm::omp::Clause::OMPC_private, + llvm::omp::Clause::OMPC_firstprivate}; if (blockDirective.v == llvm::omp::OMPD_parallel) { // Create and insert the operation. auto parallelOp = firOpBuilder.create( @@ -605,7 +618,8 @@ allocateOperands, allocatorOperands, /*reduction_vars=*/ValueRange(), /*reductions=*/nullptr, procBindKindAttr); createBodyOfOp(parallelOp, converter, currentLocation, - eval, &opClauseList); + eval, &opClauseList, /*iv=*/{}, + /*isCombined=*/false, privatizeSet); } else if (blockDirective.v == llvm::omp::OMPD_master) { auto masterOp = firOpBuilder.create(currentLocation, argTy); @@ -625,7 +639,8 @@ mergeableAttr, /*in_reduction_vars=*/ValueRange(), /*in_reductions=*/nullptr, priorityClauseOperand, allocateOperands, allocatorOperands); - createBodyOfOp(taskOp, converter, currentLocation, eval, &opClauseList); + createBodyOfOp(taskOp, converter, currentLocation, eval, &opClauseList, + /*iv=*/{}, /*isCombined=*/false, privatizeSet); } else { TODO(converter.getCurrentLocation(), "Unhandled block directive"); } @@ -709,6 +724,9 @@ const auto &loopOpClauseList = std::get( std::get(loopConstruct.t).t); + OmpClauseSet privatizeSet{llvm::omp::Clause::OMPC_private, + llvm::omp::Clause::OMPC_firstprivate}; + const auto ompDirective = std::get( std::get(loopConstruct.t).t) @@ -793,7 +811,8 @@ auto SimdLoopOp = firOpBuilder.create( currentLocation, resultType, lowerBound, upperBound, step); createBodyOfOp(SimdLoopOp, converter, currentLocation, - eval, &loopOpClauseList, iv); + eval, &loopOpClauseList, iv, + /*isCombined=*/false, privatizeSet); return; } @@ -888,7 +907,8 @@ } createBodyOfOp(wsLoopOp, converter, currentLocation, eval, - &loopOpClauseList, iv); + &loopOpClauseList, iv, /*isCombined=*/false, + privatizeSet); } static void