Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions flang/include/flang/Lower/OpenMP.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ bool markOpenMPDeferredDeclareTargetFunctions(
AbstractConverter &);
void genOpenMPRequires(mlir::Operation *, const Fortran::semantics::Symbol *);

// Materialize omp.declare_mapper ops for mapper declarations found in
// imported modules. If \p scope is null, materialize for the whole
// semantics global scope; otherwise, operate recursively starting at \p scope.
void materializeOpenMPDeclareMappers(
Fortran::lower::AbstractConverter &, Fortran::semantics::SemanticsContext &,
const Fortran::semantics::Scope *scope = nullptr);

} // namespace lower
} // namespace Fortran

Expand Down
20 changes: 19 additions & 1 deletion flang/include/flang/Semantics/symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -777,14 +777,32 @@ class UserReductionDetails {
DeclVector declList_;
};

// Used for OpenMP DECLARE MAPPER, it holds the declaration constructs
// so they can be serialized into module files and later re-parsed when
// USE-associated.
class MapperDetails {
public:
using DeclVector = std::vector<const parser::OpenMPDeclarativeConstruct *>;

MapperDetails() = default;

void AddDecl(const parser::OpenMPDeclarativeConstruct *decl) {
declList_.emplace_back(decl);
}
const DeclVector &GetDeclList() const { return declList_; }

private:
DeclVector declList_;
};

class UnknownDetails {};

using Details = std::variant<UnknownDetails, MainProgramDetails, ModuleDetails,
SubprogramDetails, SubprogramNameDetails, EntityDetails,
ObjectEntityDetails, ProcEntityDetails, AssocEntityDetails,
DerivedTypeDetails, UseDetails, UseErrorDetails, HostAssocDetails,
GenericDetails, ProcBindingDetails, NamelistDetails, CommonBlockDetails,
TypeParamDetails, MiscDetails, UserReductionDetails>;
TypeParamDetails, MiscDetails, UserReductionDetails, MapperDetails>;
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Details &);
std::string DetailsToString(const Details &);

Expand Down
7 changes: 7 additions & 0 deletions flang/lib/Lower/Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,13 @@ class FirConverter : public Fortran::lower::AbstractConverter {
}
});

// Ensure imported OpenMP declare mappers are materialized at module
// scope before lowering any constructs that may reference them.
createBuilderOutsideOfFuncOpAndDo([&]() {
Fortran::lower::materializeOpenMPDeclareMappers(
*this, bridge.getSemanticsContext());
});

// Create definitions of intrinsic module constants.
createBuilderOutsideOfFuncOpAndDo(
[&]() { createIntrinsicModuleDefinitions(pft); });
Expand Down
12 changes: 8 additions & 4 deletions flang/lib/Lower/OpenMP/ClauseProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1392,10 +1392,14 @@ bool ClauseProcessor::processMap(
}
if (mappers) {
assert(mappers->size() == 1 && "more than one mapper");
mapperIdName = mappers->front().v.id().symbol->name().ToString();
if (mapperIdName != "default")
mapperIdName = converter.mangleName(
mapperIdName, mappers->front().v.id().symbol->owner());
const semantics::Symbol *mapperSym = mappers->front().v.id().symbol;
mapperIdName = mapperSym->name().ToString();
if (mapperIdName != "default") {
// Mangle with the ultimate owner so that use-associated mapper
// identifiers resolve to the same symbol as their defining scope.
const semantics::Symbol &ultimate = mapperSym->GetUltimate();
mapperIdName = converter.mangleName(mapperIdName, ultimate.owner());
}
}

processMapObjects(stmtCtx, clauseLocation,
Expand Down
59 changes: 54 additions & 5 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3543,10 +3543,10 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
TODO(converter.getCurrentLocation(), "OpenMPDeclareSimdConstruct");
}

static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPDeclareMapperConstruct &construct) {
static void genOpenMPDeclareMapperImpl(
lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
const parser::OpenMPDeclareMapperConstruct &construct,
const semantics::Symbol *mapperSymOpt = nullptr) {
mlir::Location loc = converter.genLocation(construct.source);
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
const parser::OmpArgumentList &args = construct.v.Arguments();
Expand All @@ -3562,8 +3562,17 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
"Expected derived type");

std::string mapperNameStr = mapperName;
if (auto *sym = converter.getCurrentScope().FindSymbol(mapperNameStr))
if (mapperSymOpt && mapperNameStr != "default") {
mapperNameStr = converter.mangleName(mapperNameStr, mapperSymOpt->owner());
} else if (auto *sym =
converter.getCurrentScope().FindSymbol(mapperNameStr)) {
mapperNameStr = converter.mangleName(mapperNameStr, sym->owner());
}

// If the mapper op already exists (e.g., created by regular lowering or by
// materialization of imported mappers), do not recreate it.
if (converter.getModuleOp().lookupSymbol(mapperNameStr))
return;

// Save current insertion point before moving to the module scope to create
// the DeclareMapperOp
Expand All @@ -3586,6 +3595,13 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseOps.mapVars);
}

static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPDeclareMapperConstruct &construct) {
genOpenMPDeclareMapperImpl(converter, semaCtx, construct);
}

static void
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
Expand Down Expand Up @@ -4229,3 +4245,36 @@ void Fortran::lower::genOpenMPRequires(mlir::Operation *mod,
offloadMod.setRequires(mlirFlags);
}
}

// Walk scopes and materialize omp.declare_mapper ops for mapper declarations
// found in imported modules. If \p scope is null, start from the global scope.
void Fortran::lower::materializeOpenMPDeclareMappers(
Fortran::lower::AbstractConverter &converter,
semantics::SemanticsContext &semaCtx, const semantics::Scope *scope) {
const semantics::Scope &root = scope ? *scope : semaCtx.globalScope();

// Recurse into child scopes first (modules, submodules, etc.).
for (const semantics::Scope &child : root.children())
materializeOpenMPDeclareMappers(converter, semaCtx, &child);

// Only consider module scopes to avoid duplicating local constructs.
if (!root.IsModule())
return;

// Only materialize for modules coming from mod files to avoid duplicates.
if (!root.symbol() || !root.symbol()->test(semantics::Symbol::Flag::ModFile))
return;

// Scan symbols in this module scope for MapperDetails.
for (auto &it : root) {
const semantics::Symbol &sym = *it.second;
if (auto *md = sym.detailsIf<semantics::MapperDetails>()) {
for (const auto *decl : md->GetDeclList()) {
if (const auto *mapperDecl =
std::get_if<parser::OpenMPDeclareMapperConstruct>(&decl->u)) {
genOpenMPDeclareMapperImpl(converter, semaCtx, *mapperDecl, &sym);
}
}
}
}
}
12 changes: 12 additions & 0 deletions flang/lib/Semantics/mod-file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static void PutBound(llvm::raw_ostream &, const Bound &);
static void PutShapeSpec(llvm::raw_ostream &, const ShapeSpec &);
static void PutShape(
llvm::raw_ostream &, const ArraySpec &, char open, char close);
static void PutMapper(llvm::raw_ostream &, const Symbol &, SemanticsContext &);

static llvm::raw_ostream &PutAttr(llvm::raw_ostream &, Attr);
static llvm::raw_ostream &PutType(llvm::raw_ostream &, const DeclTypeSpec &);
Expand Down Expand Up @@ -938,6 +939,7 @@ void ModFileWriter::PutEntity(llvm::raw_ostream &os, const Symbol &symbol) {
[&](const ProcEntityDetails &) { PutProcEntity(os, symbol); },
[&](const TypeParamDetails &) { PutTypeParam(os, symbol); },
[&](const UserReductionDetails &) { PutUserReduction(os, symbol); },
[&](const MapperDetails &) { PutMapper(decls_, symbol, context_); },
[&](const auto &) {
common::die("PutEntity: unexpected details: %s",
DetailsToString(symbol.details()).c_str());
Expand Down Expand Up @@ -1101,6 +1103,16 @@ void ModFileWriter::PutUserReduction(
}
}

static void PutMapper(
llvm::raw_ostream &os, const Symbol &symbol, SemanticsContext &context) {
const auto &details{symbol.get<MapperDetails>()};
// Emit each saved DECLARE MAPPER construct as-is, so that consumers of the
// module can reparse it and recreate the mapper symbol and semantics state.
for (const auto *decl : details.GetDeclList()) {
Unparse(os, *decl, context.langOptions());
}
}

void PutInit(llvm::raw_ostream &os, const Symbol &symbol, const MaybeExpr &init,
const parser::Expr *unanalyzed, SemanticsContext &context) {
if (IsNamedConstant(symbol) || symbol.owner().IsDerivedType()) {
Expand Down
47 changes: 34 additions & 13 deletions flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1852,21 +1852,25 @@ bool OmpVisitor::Pre(const parser::OmpMapClause &x) {
// TODO: Do we need a specific flag or type here, to distinghuish against
// other ConstructName things? Leaving this for the full implementation
// of mapper lowering.
auto *misc{symbol->detailsIf<MiscDetails>()};
if (!misc || misc->kind() != MiscDetails::Kind::ConstructName)
auto &ultimate{symbol->GetUltimate()};
auto *misc{ultimate.detailsIf<MiscDetails>()};
auto *md{ultimate.detailsIf<MapperDetails>()};
if (!md && (!misc || misc->kind() != MiscDetails::Kind::ConstructName))
context().Say(mapper->v.source,
"Name '%s' should be a mapper name"_err_en_US, mapper->v.source);
else
mapper->v.symbol = symbol;
} else {
mapper->v.symbol =
&MakeSymbol(mapper->v, MiscDetails{MiscDetails::Kind::ConstructName});
// TODO: When completing the implementation, we probably want to error if
// the symbol is not declared, but right now, testing that the TODO for
// OmpMapClause happens is obscured by the TODO for declare mapper, so
// leaving this out. Remove the above line once the declare mapper is
// implemented. context().Say(mapper->v.source, "'%s' not
// declared"_err_en_US, mapper->v.source);
// Allow the special 'default' mapper identifier without prior
// declaration so lowering can recognize and handle it. Emit an
// error for any other missing mapper identifier.
if (mapper->v.source.ToString() == "default") {
mapper->v.symbol = &MakeSymbol(
mapper->v, MiscDetails{MiscDetails::Kind::ConstructName});
} else {
context().Say(
mapper->v.source, "'%s' not declared"_err_en_US, mapper->v.source);
}
}
}
return true;
Expand All @@ -1880,8 +1884,15 @@ void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
// the type has been fully processed.
BeginDeclTypeSpec();
auto &mapperName{std::get<std::string>(spec.t)};
MakeSymbol(parser::CharBlock(mapperName), Attrs{},
MiscDetails{MiscDetails::Kind::ConstructName});
// Create or update the mapper symbol with MapperDetails and
// keep track of the declarative construct for module emission.
Symbol &mapperSym{MakeSymbol(parser::CharBlock(mapperName), Attrs{})};
if (auto *md{mapperSym.detailsIf<MapperDetails>()}) {
md->AddDecl(declaratives_.back());
} else if (mapperSym.has<UnknownDetails>() || mapperSym.has<MiscDetails>()) {
mapperSym.set_details(MapperDetails{});
mapperSym.get<MapperDetails>().AddDecl(declaratives_.back());
}
PushScope(Scope::Kind::OtherConstruct, nullptr);
Walk(std::get<parser::TypeSpec>(spec.t));
auto &varName{std::get<parser::Name>(spec.t)};
Expand Down Expand Up @@ -3611,10 +3622,20 @@ void ModuleVisitor::Post(const parser::UseStmt &x) {
rename.u);
}
for (const auto &[name, symbol] : *useModuleScope_) {
// Default USE imports public names, excluding intrinsic-only and most
// miscellaneous details. Allow OpenMP mapper identifiers represented
// as MapperDetails, and also legacy MiscDetails::ConstructName.
bool isMapper{symbol->has<MapperDetails>()};
if (!isMapper) {
if (const auto *misc{symbol->detailsIf<MiscDetails>()}) {
isMapper = misc->kind() == MiscDetails::Kind::ConstructName;
}
}
if (symbol->attrs().test(Attr::PUBLIC) && !IsUseRenamed(symbol->name()) &&
(!symbol->implicitAttrs().test(Attr::INTRINSIC) ||
symbol->has<UseDetails>()) &&
!symbol->has<MiscDetails>() && useNames.count(name) == 0) {
(!symbol->has<MiscDetails>() || isMapper) &&
useNames.count(name) == 0) {
SourceName location{x.moduleName.source};
if (auto *localSymbol{FindInScope(name)}) {
DoAddUse(location, localSymbol->name(), *localSymbol, *symbol);
Expand Down
6 changes: 5 additions & 1 deletion flang/lib/Semantics/symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,8 @@ std::string DetailsToString(const Details &details) {
[](const TypeParamDetails &) { return "TypeParam"; },
[](const MiscDetails &) { return "Misc"; },
[](const AssocEntityDetails &) { return "AssocEntity"; },
[](const UserReductionDetails &) { return "UserReductionDetails"; }},
[](const UserReductionDetails &) { return "UserReductionDetails"; },
[](const MapperDetails &) { return "MapperDetails"; }},
details);
}

Expand Down Expand Up @@ -379,6 +380,7 @@ bool Symbol::CanReplaceDetails(const Details &details) const {
[&](const UserReductionDetails &) {
return has<UserReductionDetails>();
},
[&](const MapperDetails &) { return has<MapperDetails>(); },
[](const auto &) { return false; },
},
details);
Expand Down Expand Up @@ -685,6 +687,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Details &details) {
DumpType(os, type);
}
},
// Avoid recursive streaming for MapperDetails; nothing more to dump
[&](const MapperDetails &) {},
[&](const auto &x) { os << x; },
},
details);
Expand Down
26 changes: 25 additions & 1 deletion flang/test/Lower/OpenMP/declare-mapper.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-3.f90 -o - | FileCheck %t/omp-declare-mapper-3.f90
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-4.f90 -o - | FileCheck %t/omp-declare-mapper-4.f90
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-5.f90 -o - | FileCheck %t/omp-declare-mapper-5.f90
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %t/omp-declare-mapper-6.f90 -o - | FileCheck %t/omp-declare-mapper-6.f90
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-6.f90 -o - | FileCheck %t/omp-declare-mapper-6.f90
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -module-dir %t %t/omp-declare-mapper-7.mod.f90 -o - >/dev/null
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -J %t %t/omp-declare-mapper-7.use.f90 -o - | FileCheck %t/omp-declare-mapper-7.use.f90

!--- omp-declare-mapper-1.f90
subroutine declare_mapper_1
Expand Down Expand Up @@ -301,3 +303,25 @@ subroutine declare_mapper_nested_parent
r%real_arr = r%base_arr(1) + r%inner%deep_arr(1)
!$omp end target
end subroutine declare_mapper_nested_parent

!--- omp-declare-mapper-7.mod.f90
! Module with DECLARE MAPPER to be compiled separately
module m_mod
implicit none
type :: mty
integer :: x
end type mty
!$omp declare mapper(mymap : mty :: v) map(tofrom: v%x)
end module m_mod

!--- omp-declare-mapper-7.use.f90
! Consumer program that USEs the module and applies the mapper by name.
! CHECK: %{{.*}} = omp.map.info {{.*}} mapper(@{{.*mymap}}) {{.*}} {name = "a"}
program use_module_mapper
use m_mod
implicit none
type(mty) :: a
!$omp target map(mapper(mymap) : a)
a%x = 42
!$omp end target
end program use_module_mapper
7 changes: 3 additions & 4 deletions flang/test/Parser/OpenMP/map-modifiers.f90
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ subroutine f21(x, y)
integer :: x(10)
integer :: y
integer, parameter :: p = 23
!$omp target map(mapper(xx), from: x)
!$omp target map(mapper(default), from: x)
x = x + 1
!$omp end target
end
Expand All @@ -329,15 +329,15 @@ subroutine f21(x, y)
!UNPARSE: INTEGER x(10_4)
!UNPARSE: INTEGER y
!UNPARSE: INTEGER, PARAMETER :: p = 23_4
!UNPARSE: !$OMP TARGET MAP(MAPPER(XX), FROM: X)
!UNPARSE: !$OMP TARGET MAP(MAPPER(DEFAULT), FROM: X)
!UNPARSE: x=x+1_4
!UNPARSE: !$OMP END TARGET
!UNPARSE: END SUBROUTINE

!PARSE-TREE: OmpBeginDirective
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = target
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
!PARSE-TREE: | | Modifier -> OmpMapper -> Name = 'xx'
!PARSE-TREE: | | Modifier -> OmpMapper -> Name = 'default'
!PARSE-TREE: | | Modifier -> OmpMapType -> Value = From
!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'

Expand Down Expand Up @@ -375,4 +375,3 @@ subroutine f22(x)
!PARSE-TREE: | | SectionSubscript -> Integer -> Expr = 'i'
!PARSE-TREE: | | | Designator -> DataRef -> Name = 'i'
!PARSE-TREE: | bool = 'true'

14 changes: 14 additions & 0 deletions flang/test/Semantics/OpenMP/declare-mapper-modfile.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
! RUN: split-file %s %t
! RUN: %flang_fc1 -fsyntax-only -fopenmp -fopenmp-version=50 -module-dir %t %t/m.f90
! RUN: cat %t/m.mod | FileCheck --ignore-case %s

!--- m.f90
module m
implicit none
type :: t
integer :: x
end type t
!$omp declare mapper(mymap : t :: v) map(v%x)
end module m

!CHECK: !$OMP DECLARE MAPPER(mymap:t::v) MAP(v%x)
Loading
Loading