diff --git a/flang/include/flang/Lower/OpenMP/Clauses.h b/flang/include/flang/Lower/OpenMP/Clauses.h index 737b535d604d6..455eda2738e6d 100644 --- a/flang/include/flang/Lower/OpenMP/Clauses.h +++ b/flang/include/flang/Lower/OpenMP/Clauses.h @@ -113,6 +113,8 @@ Object makeObject(const parser::Designator &dsg, semantics::SemanticsContext &semaCtx); Object makeObject(const parser::StructureComponent &comp, semantics::SemanticsContext &semaCtx); +Object makeObject(const parser::EntityDecl &decl, + semantics::SemanticsContext &semaCtx); inline auto makeObjectFn(semantics::SemanticsContext &semaCtx) { return [&](auto &&s) { return makeObject(s, semaCtx); }; @@ -172,6 +174,7 @@ std::optional getBaseObject(const Object &object, semantics::SemanticsContext &semaCtx); namespace clause { +using StylizedInstance = tomp::type::StylizedInstanceT; using Range = tomp::type::RangeT; using Mapper = tomp::type::MapperT; using Iterator = tomp::type::IteratorT; diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h index f5739ab16d643..639f7224ddf6b 100644 --- a/flang/include/flang/Semantics/openmp-utils.h +++ b/flang/include/flang/Semantics/openmp-utils.h @@ -97,6 +97,8 @@ const SomeExpr *HasStorageOverlap( const SomeExpr &base, llvm::ArrayRef exprs); bool IsAssignment(const parser::ActionStmt *x); bool IsPointerAssignment(const evaluate::Assignment &x); + +MaybeExpr MakeEvaluateExpr(const parser::OmpStylizedInstance &inp); } // namespace omp } // namespace Fortran::semantics diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 451b53e71b31b..3c31b3a07f57f 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -383,36 +383,36 @@ bool ClauseProcessor::processInclusive( } bool ClauseProcessor::processInitializer( - lower::SymMap &symMap, const parser::OmpClause::Initializer &inp, + lower::SymMap &symMap, ReductionProcessor::GenInitValueCBTy &genInitValueCB) const { if (auto *clause = findUniqueClause()) { genInitValueCB = [&, clause](fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type type, mlir::Value ompOrig) { lower::SymMapScope scope(symMap); - const parser::OmpInitializerExpression &iexpr = inp.v.v; - const parser::OmpStylizedInstance &styleInstance = iexpr.v.front(); - const std::list &declList = - std::get>(styleInstance.t); mlir::Value ompPrivVar; - for (const parser::OmpStylizedDeclaration &decl : declList) { - auto &name = std::get(decl.var.t); - assert(name.symbol && "Name does not have a symbol"); + const clause::StylizedInstance &inst = clause->v.front(); + + for (const Object &object : + std::get(inst.t)) { mlir::Value addr = builder.createTemporary(loc, ompOrig.getType()); fir::StoreOp::create(builder, loc, ompOrig, addr); fir::FortranVariableFlagsEnum extraFlags = {}; fir::FortranVariableFlagsAttr attributes = - Fortran::lower::translateSymbolAttributes(builder.getContext(), - *name.symbol, extraFlags); - auto declareOp = hlfir::DeclareOp::create( - builder, loc, addr, name.ToString(), nullptr, {}, nullptr, nullptr, - 0, attributes); - if (name.ToString() == "omp_priv") + Fortran::lower::translateSymbolAttributes( + builder.getContext(), *object.sym(), extraFlags); + std::string name = object.sym()->name().ToString(); + auto declareOp = + hlfir::DeclareOp::create(builder, loc, addr, name, nullptr, {}, + nullptr, nullptr, 0, attributes); + if (name == "omp_priv") ompPrivVar = declareOp.getResult(0); - symMap.addVariableDefinition(*name.symbol, declareOp); + symMap.addVariableDefinition(*object.sym(), declareOp); } + // Lower the expression/function call lower::StatementContext stmtCtx; - const semantics::SomeExpr &initExpr = clause->v.front(); + const semantics::SomeExpr &initExpr = + std::get(inst.t); mlir::Value result = common::visit( common::visitors{ [&](const evaluate::ProcedureRef &procRef) -> mlir::Value { diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h index 3485a4ed1581f..a04cd4b79dd24 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.h +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h @@ -20,7 +20,7 @@ #include "flang/Lower/OpenMP/Clauses.h" #include "flang/Lower/Support/ReductionProcessor.h" #include "flang/Optimizer/Builder/Todo.h" -#include "flang/Parser/parse-tree.h" +#include "flang/Parser/char-block.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" namespace fir { @@ -89,7 +89,7 @@ class ClauseProcessor { bool processInclusive(mlir::Location currentLocation, mlir::omp::InclusiveClauseOps &result) const; bool processInitializer( - lower::SymMap &symMap, const parser::OmpClause::Initializer &inp, + lower::SymMap &symMap, ReductionProcessor::GenInitValueCBTy &genInitValueCB) const; bool processMergeable(mlir::omp::MergeableClauseOps &result) const; bool processNogroup(mlir::omp::NogroupClauseOps &result) const; diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 11f558e6cc8ca..9ea4e8fcd6c0e 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -13,6 +13,7 @@ #include "flang/Parser/parse-tree.h" #include "flang/Semantics/expression.h" #include "flang/Semantics/openmp-modifiers.h" +#include "flang/Semantics/openmp-utils.h" #include "flang/Semantics/symbol.h" #include @@ -128,6 +129,11 @@ Object makeObject(const parser::OmpObject &object, return makeObject(std::get(object.u), semaCtx); } +Object makeObject(const parser::EntityDecl &decl, + semantics::SemanticsContext &semaCtx) { + return makeObject(std::get(decl.t), semaCtx); +} + ObjectList makeObjects(const parser::OmpArgumentList &objects, semantics::SemanticsContext &semaCtx) { return makeList(objects.v, [&](const parser::OmpArgument &arg) { @@ -275,12 +281,10 @@ makeIteratorSpecifiers(const parser::OmpIteratorSpecifier &inp, auto &tds = std::get(inp.t); auto &entities = std::get>(tds.t); for (const parser::EntityDecl &ed : entities) { - auto &name = std::get(ed.t); - assert(name.symbol && "Expecting symbol for iterator variable"); - auto *stype = name.symbol->GetType(); - assert(stype && "Expecting symbol type"); - IteratorSpecifier spec{{evaluate::DynamicType::From(*stype), - makeObject(name, semaCtx), range}}; + auto *symbol = std::get(ed.t).symbol; + auto *type = DEREF(symbol).GetType(); + IteratorSpecifier spec{{evaluate::DynamicType::From(DEREF(type)), + makeObject(ed, semaCtx), range}}; specifiers.emplace_back(std::move(spec)); } @@ -983,19 +987,24 @@ Initializer make(const parser::OmpClause::Initializer &inp, semantics::SemanticsContext &semaCtx) { const parser::OmpInitializerExpression &iexpr = inp.v.v; Initializer initializer; - for (const parser::OmpStylizedInstance &styleInstance : iexpr.v) { - auto &instance = - std::get(styleInstance.t); - if (const auto *as = std::get_if(&instance.u)) { - auto &expr = std::get(as->t); - initializer.v.push_back(makeExpr(expr, semaCtx)); - } else if (const auto *call = std::get_if(&instance.u)) { - assert(call->typedCall && "Expecting typedCall"); - const auto &procRef = *call->typedCall; - initializer.v.push_back(semantics::SomeExpr(procRef)); - } else { - llvm_unreachable("Unexpected initializer"); - } + + for (const parser::OmpStylizedInstance &sinst : iexpr.v) { + ObjectList variables; + llvm::transform( + std::get>(sinst.t), + std::back_inserter(variables), + [&](const parser::OmpStylizedDeclaration &s) { + return makeObject(s.var, semaCtx); + }); + + SomeExpr instance = [&]() { + if (auto &&expr = semantics::omp::MakeEvaluateExpr(sinst)) + return std::move(*expr); + llvm_unreachable("Expecting expression instance"); + }(); + + initializer.v.push_back( + StylizedInstance{{std::move(variables), std::move(instance)}}); } return initializer; diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 582e684442dfc..38ab42076f559 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -3764,9 +3764,7 @@ static void genOMP( List clauses = makeClauses(initializer, semaCtx); ReductionProcessor::GenInitValueCBTy genInitValueCB; ClauseProcessor cp(converter, semaCtx, clauses); - const parser::OmpClause::Initializer &iclause{ - std::get(initializer.v.front().u)}; - cp.processInitializer(symTable, iclause, genInitValueCB); + cp.processInitializer(symTable, genInitValueCB); const auto &identifier = std::get(specifier.t); const auto &designator = diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp index 18a37d64a3b5a..a3912f31b4452 100644 --- a/flang/lib/Semantics/openmp-utils.cpp +++ b/flang/lib/Semantics/openmp-utils.cpp @@ -496,4 +496,24 @@ bool IsPointerAssignment(const evaluate::Assignment &x) { return std::holds_alternative(x.u) || std::holds_alternative(x.u); } + +MaybeExpr MakeEvaluateExpr(const parser::OmpStylizedInstance &inp) { + auto &instance = std::get(inp.t); + + return common::visit( // + common::visitors{ + [&](const parser::AssignmentStmt &s) -> MaybeExpr { + return GetEvaluateExpr(std::get(s.t)); + }, + [&](const parser::CallStmt &s) -> MaybeExpr { + assert(s.typedCall && "Expecting typedCall"); + const auto &procRef = *s.typedCall; + return SomeExpr(procRef); + }, + [&](const common::Indirection &s) -> MaybeExpr { + return GetEvaluateExpr(s.value()); + }, + }, + instance.u); +} } // namespace Fortran::semantics::omp diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h index cf401711173e7..0a0323559eb27 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h @@ -189,6 +189,14 @@ template using ObjectListT = ListT>; using DirectiveName = llvm::omp::Directive; +template // +struct StylizedInstanceT { + using Variables = ObjectListT; + using Instance = E; + using TupleTrait = std::true_type; + std::tuple t; +}; + template // struct DefinedOperatorT { struct DefinedOpName { @@ -762,8 +770,7 @@ struct InitT { // V5.2: [5.5.4] `initializer` clause template // struct InitializerT { - using InitializerExpr = E; - using List = ListT; + using List = ListT>; using WrapperTrait = std::true_type; List v; };