Skip to content

[OpenMP][Flang] Emit default declare mappers implicitly for derived types #140562

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3540,7 +3540,7 @@ WRAPPER_CLASS(OmpLocatorList, std::list<OmpLocator>);
struct OmpMapperSpecifier {
// Absent mapper-identifier is equivalent to DEFAULT.
TUPLE_CLASS_BOILERPLATE(OmpMapperSpecifier);
std::tuple<std::optional<Name>, TypeSpec, Name> t;
std::tuple<std::string, TypeSpec, Name> t;
};

// Ref: [4.5:222:1-5], [5.0:305:20-27], [5.1:337:11-19], [5.2:139:18-23],
Expand Down
35 changes: 21 additions & 14 deletions flang/lib/Lower/OpenMP/ClauseProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1102,23 +1102,30 @@ void ClauseProcessor::processMapObjects(

auto getDefaultMapperID = [&](const omp::Object &object,
std::string &mapperIdName) {
if (!mlir::isa<mlir::omp::DeclareMapperOp>(
firOpBuilder.getRegion().getParentOp())) {
const semantics::DerivedTypeSpec *typeSpec = nullptr;

if (object.sym()->owner().IsDerivedType())
typeSpec = object.sym()->owner().derivedTypeSpec();
else if (object.sym()->GetType() &&
object.sym()->GetType()->category() ==
semantics::DeclTypeSpec::TypeDerived)
typeSpec = &object.sym()->GetType()->derivedTypeSpec();

if (typeSpec) {
mapperIdName = typeSpec->name().ToString() + ".default";
const semantics::DerivedTypeSpec *typeSpec = nullptr;

if (object.sym()->GetType() && object.sym()->GetType()->category() ==
semantics::DeclTypeSpec::TypeDerived)
typeSpec = &object.sym()->GetType()->derivedTypeSpec();
else if (object.sym()->owner().IsDerivedType())
typeSpec = object.sym()->owner().derivedTypeSpec();

if (typeSpec) {
mapperIdName = typeSpec->name().ToString() + ".omp.default.mapper";
if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName))
mapperIdName = converter.mangleName(mapperIdName, sym->owner());
else
mapperIdName =
converter.mangleName(mapperIdName, *typeSpec->GetScope());
}
}

// Make sure we don't return a mapper to self
llvm::StringRef parentOpName;
if (auto declMapOp = mlir::dyn_cast<mlir::omp::DeclareMapperOp>(
firOpBuilder.getRegion().getParentOp()))
parentOpName = declMapOp.getSymName();
if (mapperIdName == parentOpName)
mapperIdName = "";
};

// Create the mapper symbol from its name, if specified.
Expand Down
151 changes: 136 additions & 15 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2348,6 +2348,122 @@ genSingleOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
queue, item, clauseOps);
}

static mlir::FlatSymbolRefAttr
genImplicitDefaultDeclareMapper(lower::AbstractConverter &converter,
mlir::Location loc, fir::RecordType recordType,
llvm::StringRef mapperNameStr) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();

// Save current insertion point before moving to the module scope to create
// the DeclareMapperOp
mlir::OpBuilder::InsertionGuard guard(firOpBuilder);

firOpBuilder.setInsertionPointToStart(converter.getModuleOp().getBody());
auto declMapperOp = firOpBuilder.create<mlir::omp::DeclareMapperOp>(
loc, mapperNameStr, recordType);
auto &region = declMapperOp.getRegion();
firOpBuilder.createBlock(&region);
auto mapperArg = region.addArgument(firOpBuilder.getRefType(recordType), loc);

auto declareOp =
firOpBuilder.create<hlfir::DeclareOp>(loc, mapperArg, /*uniq_name=*/"");

const auto genBoundsOps = [&](mlir::Value mapVal,
llvm::SmallVectorImpl<mlir::Value> &bounds) {
fir::ExtendedValue extVal =
hlfir::translateToExtendedValue(mapVal.getLoc(), firOpBuilder,
hlfir::Entity{mapVal},
/*contiguousHint=*/true)
.first;
fir::factory::AddrAndBoundsInfo info = fir::factory::getDataOperandBaseAddr(
firOpBuilder, mapVal, /*isOptional=*/false, mapVal.getLoc());
bounds = fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
mlir::omp::MapBoundsType>(
firOpBuilder, info, extVal,
/*dataExvIsAssumedSize=*/false, mapVal.getLoc());
};

// Return a reference to the contents of a derived type with one field.
// Also return the field type.
const auto getFieldRef =
[&](mlir::Value rec,
unsigned index) -> std::tuple<mlir::Value, mlir::Type> {
auto recType = mlir::dyn_cast<fir::RecordType>(
fir::unwrapPassByRefType(rec.getType()));
auto [fieldName, fieldTy] = recType.getTypeList()[index];
mlir::Value field = firOpBuilder.create<fir::FieldIndexOp>(
loc, fir::FieldType::get(recType.getContext()), fieldName, recType,
fir::getTypeParams(rec));
return {firOpBuilder.create<fir::CoordinateOp>(
loc, firOpBuilder.getRefType(fieldTy), rec, field),
fieldTy};
};

mlir::omp::DeclareMapperInfoOperands clauseOps;
llvm::SmallVector<llvm::SmallVector<int64_t>> memberPlacementIndices;
llvm::SmallVector<mlir::Value> memberMapOps;

llvm::omp::OpenMPOffloadMappingFlags mapFlag =
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM |
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
mlir::omp::VariableCaptureKind captureKind =
mlir::omp::VariableCaptureKind::ByRef;
int64_t index = 0;

// Populate the declareMapper region with the map information.
for (const auto &[memberName, memberType] :
mlir::dyn_cast<fir::RecordType>(recordType).getTypeList()) {
auto [ref, type] = getFieldRef(declareOp.getBase(), index);
mlir::FlatSymbolRefAttr mapperId;
if (auto recType = mlir::dyn_cast<fir::RecordType>(memberType)) {
std::string mapperIdName =
recType.getName().str() + ".omp.default.mapper";
if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName))
mapperIdName = converter.mangleName(mapperIdName, sym->owner());
else if (auto *sym = converter.getCurrentScope().FindSymbol(memberName))
mapperIdName = converter.mangleName(mapperIdName, sym->owner());

if (converter.getModuleOp().lookupSymbol(mapperIdName))
mapperId = mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(),
mapperIdName);
else
mapperId = genImplicitDefaultDeclareMapper(converter, loc, recType,
mapperIdName);
}

llvm::SmallVector<mlir::Value> bounds;
genBoundsOps(ref, bounds);
mlir::Value mapOp = createMapInfoOp(
firOpBuilder, loc, ref, /*varPtrPtr=*/mlir::Value{}, "", bounds,
/*members=*/{},
/*membersIndex=*/mlir::ArrayAttr{},
static_cast<
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
mapFlag),
captureKind, ref.getType(), /*partialMap=*/false, mapperId);
memberMapOps.emplace_back(mapOp);
memberPlacementIndices.emplace_back(llvm::SmallVector<int64_t>{index++});
}

llvm::SmallVector<mlir::Value> bounds;
genBoundsOps(declareOp.getOriginalBase(), bounds);
mlir::omp::MapInfoOp mapOp = createMapInfoOp(
firOpBuilder, loc, declareOp.getOriginalBase(),
/*varPtrPtr=*/mlir::Value(), /*name=*/"", bounds, memberMapOps,
firOpBuilder.create2DI64ArrayAttr(memberPlacementIndices),
static_cast<std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
mapFlag),
captureKind, declareOp.getType(0),
/*partialMap=*/true);

clauseOps.mapVars.emplace_back(mapOp);

firOpBuilder.create<mlir::omp::DeclareMapperInfoOp>(loc, clauseOps.mapVars);
return mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(),
mapperNameStr);
}

static mlir::omp::TargetOp
genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
lower::StatementContext &stmtCtx,
Expand Down Expand Up @@ -2420,13 +2536,26 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
name << sym.name().ToString();

mlir::FlatSymbolRefAttr mapperId;
if (sym.GetType()->category() == semantics::DeclTypeSpec::TypeDerived) {
if (sym.GetType()->category() == semantics::DeclTypeSpec::TypeDerived &&
defaultMaps.empty()) {
auto &typeSpec = sym.GetType()->derivedTypeSpec();
std::string mapperIdName = typeSpec.name().ToString() + ".default";
mapperIdName = converter.mangleName(mapperIdName, *typeSpec.GetScope());
std::string mapperIdName =
typeSpec.name().ToString() + ".omp.default.mapper";
if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName))
mapperIdName = converter.mangleName(mapperIdName, sym->owner());
else
mapperIdName =
converter.mangleName(mapperIdName, *typeSpec.GetScope());

if (converter.getModuleOp().lookupSymbol(mapperIdName))
mapperId = mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(),
mapperIdName);
else
mapperId = genImplicitDefaultDeclareMapper(
converter, loc,
mlir::cast<fir::RecordType>(
converter.genType(sym.GetType()->derivedTypeSpec())),
mapperIdName);
}

fir::factory::AddrAndBoundsInfo info =
Expand Down Expand Up @@ -4005,24 +4134,16 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
lower::StatementContext stmtCtx;
const auto &spec =
std::get<parser::OmpMapperSpecifier>(declareMapperConstruct.t);
const auto &mapperName{std::get<std::optional<parser::Name>>(spec.t)};
const auto &mapperName{std::get<std::string>(spec.t)};
const auto &varType{std::get<parser::TypeSpec>(spec.t)};
const auto &varName{std::get<parser::Name>(spec.t)};
assert(varType.declTypeSpec->category() ==
semantics::DeclTypeSpec::Category::TypeDerived &&
"Expected derived type");

std::string mapperNameStr;
if (mapperName.has_value()) {
mapperNameStr = mapperName->ToString();
mapperNameStr =
converter.mangleName(mapperNameStr, mapperName->symbol->owner());
} else {
mapperNameStr =
varType.declTypeSpec->derivedTypeSpec().name().ToString() + ".default";
mapperNameStr = converter.mangleName(
mapperNameStr, *varType.declTypeSpec->derivedTypeSpec().GetScope());
}
std::string mapperNameStr = mapperName;
if (auto *sym = converter.getCurrentScope().FindSymbol(mapperNameStr))
mapperNameStr = converter.mangleName(mapperNameStr, sym->owner());

// Save current insertion point before moving to the module scope to create
// the DeclareMapperOp
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ class MapInfoFinalizationPass
getDescriptorMapType(mapType, target)),
op.getMapCaptureTypeAttr(), /*varPtrPtr=*/mlir::Value{}, newMembers,
newMembersAttr, /*bounds=*/mlir::SmallVector<mlir::Value>{},
/*mapperId*/ mlir::FlatSymbolRefAttr(), op.getNameAttr(),
op.getMapperIdAttr(), op.getNameAttr(),
/*partial_map=*/builder.getBoolAttr(false));
op.replaceAllUsesWith(newDescParentMapOp.getResult());
op->erase();
Expand Down
22 changes: 21 additions & 1 deletion flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1389,8 +1389,28 @@ TYPE_PARSER(
TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>(
verbatim("DECLARE TARGET"_tok), Parser<OmpDeclareTargetSpecifier>{})))

static OmpMapperSpecifier ConstructOmpMapperSpecifier(
std::optional<Name> &&mapperName, TypeSpec &&typeSpec, Name &&varName) {
// If a name is present, parse: name ":" typeSpec "::" name
// This matches the syntax: <mapper-name> : <type-spec> :: <variable-name>
if (mapperName.has_value() && mapperName->ToString() != "default") {
return OmpMapperSpecifier{
mapperName->ToString(), std::move(typeSpec), std::move(varName)};
}
// If the name is missing, use the DerivedTypeSpec name to construct the
// default mapper name.
// This matches the syntax: <type-spec> :: <variable-name>
if (auto *derived = std::get_if<DerivedTypeSpec>(&typeSpec.u)) {
return OmpMapperSpecifier{
std::get<Name>(derived->t).ToString() + ".omp.default.mapper",
std::move(typeSpec), std::move(varName)};
}
return OmpMapperSpecifier{std::string("omp.default.mapper"),
std::move(typeSpec), std::move(varName)};
}

// mapper-specifier
TYPE_PARSER(construct<OmpMapperSpecifier>(
TYPE_PARSER(applyFunction<OmpMapperSpecifier>(ConstructOmpMapperSpecifier,
maybe(name / ":" / !":"_tok), typeSpec / "::", name))

// OpenMP 5.2: 5.8.8 Declare Mapper Construct
Expand Down
11 changes: 8 additions & 3 deletions flang/lib/Parser/unparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2093,7 +2093,11 @@ class UnparseVisitor {
Walk(x.v, ",");
}
void Unparse(const OmpMapperSpecifier &x) {
Walk(std::get<std::optional<Name>>(x.t), ":");
const auto &mapperName = std::get<std::string>(x.t);
if (mapperName.find("omp.default.mapper") == std::string::npos) {
Walk(mapperName);
Put(":");
}
Walk(std::get<TypeSpec>(x.t));
Put("::");
Walk(std::get<Name>(x.t));
Expand Down Expand Up @@ -2796,8 +2800,9 @@ class UnparseVisitor {
BeginOpenMP();
Word("!$OMP DECLARE MAPPER (");
const auto &spec{std::get<OmpMapperSpecifier>(z.t)};
if (auto mapname{std::get<std::optional<Name>>(spec.t)}) {
Walk(mapname);
const auto &mapperName = std::get<std::string>(spec.t);
if (mapperName.find("omp.default.mapper") == std::string::npos) {
Walk(mapperName);
Put(":");
}
Walk(std::get<TypeSpec>(spec.t));
Expand Down
13 changes: 4 additions & 9 deletions flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "flang/Semantics/type.h"
#include "flang/Support/Fortran.h"
#include "flang/Support/default-kinds.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/raw_ostream.h"
#include <list>
#include <map>
Expand Down Expand Up @@ -1766,15 +1767,9 @@ void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
// just following the natural flow, the map clauses gets processed before
// the type has been fully processed.
BeginDeclTypeSpec();
if (auto &mapperName{std::get<std::optional<parser::Name>>(spec.t)}) {
mapperName->symbol =
&MakeSymbol(*mapperName, MiscDetails{MiscDetails::Kind::ConstructName});
} else {
const parser::CharBlock defaultName{"default", 7};
MakeSymbol(
defaultName, Attrs{}, MiscDetails{MiscDetails::Kind::ConstructName});
}

auto &mapperName{std::get<std::string>(spec.t)};
MakeSymbol(parser::CharBlock(mapperName), Attrs{},
MiscDetails{MiscDetails::Kind::ConstructName});
PushScope(Scope::Kind::OtherConstruct, nullptr);
Walk(std::get<parser::TypeSpec>(spec.t));
auto &varName{std::get<parser::Name>(spec.t)};
Expand Down
Loading