mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 11:02:04 +08:00
[Flang][OpenMP] Update declare mapper lookup via use-module (#167903)
This commit is contained in:
@@ -41,6 +41,7 @@ struct OmpClauseList;
|
||||
|
||||
namespace semantics {
|
||||
class Symbol;
|
||||
class Scope;
|
||||
class SemanticsContext;
|
||||
} // namespace semantics
|
||||
|
||||
@@ -97,6 +98,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
|
||||
|
||||
|
||||
@@ -777,6 +777,24 @@ private:
|
||||
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,
|
||||
@@ -784,7 +802,7 @@ using Details = std::variant<UnknownDetails, MainProgramDetails, ModuleDetails,
|
||||
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 &);
|
||||
|
||||
|
||||
@@ -448,6 +448,13 @@ public:
|
||||
}
|
||||
});
|
||||
|
||||
// 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); });
|
||||
|
||||
@@ -1397,10 +1397,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,
|
||||
|
||||
@@ -3553,10 +3553,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();
|
||||
@@ -3572,8 +3572,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
|
||||
@@ -3596,6 +3605,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,
|
||||
@@ -4231,3 +4247,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 &);
|
||||
@@ -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());
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
@@ -1880,8 +1884,16 @@ 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.
|
||||
SourceName mapperSource{context().SaveTempName(std::string{mapperName})};
|
||||
Symbol &mapperSym{MakeSymbol(mapperSource, Attrs{})};
|
||||
if (!mapperSym.detailsIf<MapperDetails>()) {
|
||||
mapperSym.set_details(MapperDetails{});
|
||||
}
|
||||
if (!context().langOptions().OpenMPSimd) {
|
||||
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)};
|
||||
@@ -3611,10 +3623,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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -329,7 +329,7 @@ end
|
||||
!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
|
||||
@@ -337,7 +337,7 @@ end
|
||||
!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'
|
||||
|
||||
@@ -375,4 +375,3 @@ end
|
||||
!PARSE-TREE: | | SectionSubscript -> Integer -> Expr = 'i'
|
||||
!PARSE-TREE: | | | Designator -> DataRef -> Name = 'i'
|
||||
!PARSE-TREE: | bool = 'true'
|
||||
|
||||
|
||||
14
flang/test/Semantics/OpenMP/declare-mapper-modfile.f90
Normal file
14
flang/test/Semantics/OpenMP/declare-mapper-modfile.f90
Normal file
@@ -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)
|
||||
@@ -11,9 +11,9 @@ program main
|
||||
!$omp declare mapper(ty :: maptwo) map(maptwo, maptwo%x)
|
||||
|
||||
!! Note, symbols come out in their respective scope, but not in declaration order.
|
||||
!CHECK: mymapper: Misc ConstructName
|
||||
!CHECK: mymapper: MapperDetails
|
||||
!CHECK: ty: DerivedType components: x
|
||||
!CHECK: ty.omp.default.mapper: Misc ConstructName
|
||||
!CHECK: ty.omp.default.mapper: MapperDetails
|
||||
!CHECK: DerivedType scope: ty
|
||||
!CHECK: OtherConstruct scope:
|
||||
!CHECK: mapped (OmpMapToFrom) {{.*}} ObjectEntity type: TYPE(ty)
|
||||
@@ -21,4 +21,3 @@ program main
|
||||
!CHECK: maptwo (OmpMapToFrom) {{.*}} ObjectEntity type: TYPE(ty)
|
||||
|
||||
end program main
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
! RUN: %flang_fc1 -fdebug-dump-symbols -fopenmp -fopenmp-version=50 %s | FileCheck %s
|
||||
program main
|
||||
!CHECK-LABEL: MainProgram scope: MAIN
|
||||
type ty
|
||||
real(4) :: x
|
||||
end type ty
|
||||
!$omp declare mapper(xx : ty :: v) map(v)
|
||||
integer, parameter :: n = 256
|
||||
real(8) :: a(256)
|
||||
type(ty) :: a(256)
|
||||
!$omp target map(mapper(xx), from:a)
|
||||
do i=1,n
|
||||
a(i) = 4.2
|
||||
a(i)%x = 4.2
|
||||
end do
|
||||
!$omp end target
|
||||
!CHECK: OtherConstruct scope: size=0 alignment=1 sourceRange=74 bytes
|
||||
!CHECK: OtherClause scope: size=0 alignment=1 sourceRange=0 bytes
|
||||
!CHECK: xx: Misc ConstructName
|
||||
!CHECK: xx: MapperDetails
|
||||
end program main
|
||||
|
||||
Reference in New Issue
Block a user