[flang-commits] [flang] [llvm] [Flang][OpenMP] Initial defaultmap implementation (PR #135226)
via flang-commits
flang-commits at lists.llvm.org
Thu Apr 10 11:00:01 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-offload
Author: None (agozillon)
<details>
<summary>Changes</summary>
This aims to implement most of the initial arguments for defaultmap aside from firstprivate and none, and some of the more recent OpenMP 6 additions which will come in subsequent updates (with the OpenMP 6 variants needing parsing/semantic support first).
---
Patch is 31.34 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135226.diff
13 Files Affected:
- (modified) flang/include/flang/Parser/parse-tree.h (+2-2)
- (modified) flang/lib/Lower/OpenMP/ClauseProcessor.cpp (+20)
- (modified) flang/lib/Lower/OpenMP/ClauseProcessor.h (+6)
- (modified) flang/lib/Lower/OpenMP/Clauses.cpp (+1-1)
- (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+148-50)
- (modified) flang/lib/Parser/openmp-parsers.cpp (+3-2)
- (added) flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90 (+11)
- (added) flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90 (+11)
- (removed) flang/test/Lower/OpenMP/Todo/defaultmap-clause.f90 (-8)
- (added) flang/test/Lower/OpenMP/defaultmap.f90 (+105)
- (modified) flang/test/Parser/OpenMP/defaultmap-clause.f90 (+16)
- (added) offload/test/offloading/fortran/target-defaultmap-present.f90 (+34)
- (added) offload/test/offloading/fortran/target-defaultmap.f90 (+166)
``````````diff
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index eeb438991feee..e16ff22965a4e 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4133,8 +4133,8 @@ struct OmpDefaultClause {
// PRESENT // since 5.1
struct OmpDefaultmapClause {
TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause);
- ENUM_CLASS(
- ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default)
+ ENUM_CLASS(ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None,
+ Default, Present)
MODIFIER_BOILERPLATE(OmpVariableCategory);
std::tuple<ImplicitBehavior, MODIFIERS()> t;
};
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 44796994b244c..4d91844a7f0d3 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -856,6 +856,26 @@ static bool isVectorSubscript(const evaluate::Expr<T> &expr) {
return false;
}
+bool ClauseProcessor::processDefaultMap(
+ DefaultMapsTy &result, lower::StatementContext &stmtCtx) const {
+ auto process = [&](const omp::clause::Defaultmap &clause,
+ const parser::CharBlock &) {
+ using Defmap = omp::clause::Defaultmap;
+ clause::Defaultmap::VariableCategory variableCategory =
+ Defmap::VariableCategory::All;
+ // Variable Category is optional, if not specified defaults to all.
+ // Multiples of the same category are illegal as are any other
+ // defaultmaps being specified when a user specified all is in place,
+ // however, this should be handled earlier during semantics.
+ if (auto varCat =
+ std::get<std::optional<Defmap::VariableCategory>>(clause.t))
+ variableCategory = varCat.value_or(Defmap::VariableCategory::All);
+ auto behaviour = std::get<Defmap::ImplicitBehavior>(clause.t);
+ result.insert({variableCategory, behaviour});
+ };
+ return findRepeatableClause<omp::clause::Defaultmap>(process);
+}
+
bool ClauseProcessor::processDepend(lower::SymMap &symMap,
lower::StatementContext &stmtCtx,
mlir::omp::DependClauseOps &result) const {
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h
index bdddeb145b496..ab4680607d236 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.h
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h
@@ -32,6 +32,10 @@ namespace Fortran {
namespace lower {
namespace omp {
+// Container type for tracking user specified Defaultmaps for a target region
+using DefaultMapsTy = std::map<clause::Defaultmap::VariableCategory,
+ clause::Defaultmap::ImplicitBehavior>;
+
/// Class that handles the processing of OpenMP clauses.
///
/// Its `process<ClauseName>()` methods perform MLIR code generation for their
@@ -106,6 +110,8 @@ class ClauseProcessor {
bool processCopyin() const;
bool processCopyprivate(mlir::Location currentLocation,
mlir::omp::CopyprivateClauseOps &result) const;
+ bool processDefaultMap(DefaultMapsTy &result,
+ lower::StatementContext &stmtCtx) const;
bool processDepend(lower::SymMap &symMap, lower::StatementContext &stmtCtx,
mlir::omp::DependClauseOps &result) const;
bool
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 3ffdf7138b035..eadb3c14a4dcf 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -611,7 +611,7 @@ Defaultmap make(const parser::OmpClause::Defaultmap &inp,
MS(Firstprivate, Firstprivate)
MS(None, None)
MS(Default, Default)
- // MS(, Present) missing-in-parser
+ MS(Present, Present)
// clang-format on
);
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 312557d5da07e..5bf81424979bc 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -1700,6 +1700,7 @@ static void genTargetClauses(
lower::SymMap &symTable, lower::StatementContext &stmtCtx,
lower::pft::Evaluation &eval, const List<Clause> &clauses,
mlir::Location loc, mlir::omp::TargetOperands &clauseOps,
+ DefaultMapsTy &defaultMaps,
llvm::SmallVectorImpl<const semantics::Symbol *> &hasDeviceAddrSyms,
llvm::SmallVectorImpl<const semantics::Symbol *> &isDevicePtrSyms,
llvm::SmallVectorImpl<const semantics::Symbol *> &mapSyms) {
@@ -1718,10 +1719,11 @@ static void genTargetClauses(
cp.processMap(loc, stmtCtx, clauseOps, &mapSyms);
cp.processNowait(clauseOps);
cp.processThreadLimit(stmtCtx, clauseOps);
+ cp.processDefaultMap(defaultMaps, stmtCtx);
- cp.processTODO<clause::Allocate, clause::Defaultmap, clause::Firstprivate,
- clause::InReduction, clause::UsesAllocators>(
- loc, llvm::omp::Directive::OMPD_target);
+ cp.processTODO<clause::Allocate, clause::Firstprivate, clause::InReduction,
+ clause::UsesAllocators>(loc,
+ llvm::omp::Directive::OMPD_target);
// `target private(..)` is only supported in delayed privatization mode.
if (!enableDelayedPrivatizationStaging)
@@ -2246,10 +2248,12 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
hostEvalInfo.emplace_back();
mlir::omp::TargetOperands clauseOps;
+ DefaultMapsTy defaultMaps;
llvm::SmallVector<const semantics::Symbol *> mapSyms, isDevicePtrSyms,
hasDeviceAddrSyms;
genTargetClauses(converter, semaCtx, symTable, stmtCtx, eval, item->clauses,
- loc, clauseOps, hasDeviceAddrSyms, isDevicePtrSyms, mapSyms);
+ loc, clauseOps, defaultMaps, hasDeviceAddrSyms,
+ isDevicePtrSyms, mapSyms);
DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval,
/*shouldCollectPreDeterminedSymbols=*/
@@ -2272,6 +2276,129 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
return size <= ptrSize && align <= ptrAlign;
};
+ auto getDefaultmapIfPresent = [&](mlir::Type varType) {
+ using defMap = clause::Defaultmap;
+ auto exists = [&](defMap::VariableCategory varCat) {
+ return defaultMaps.find(varCat) != defaultMaps.end();
+ };
+
+ if (defaultMaps.empty())
+ return defMap::ImplicitBehavior::Default;
+
+ if (exists(defMap::VariableCategory::All))
+ return defaultMaps[defMap::VariableCategory::All];
+
+ // NOTE: Unsure if complex and/or vector falls into a scalar type
+ // or aggregate, but the current default implicit behaviour is to
+ // treat them as such (c_ptr has its own behaviour, so perhaps
+ // being lumped in as a scalar isn't the right thing).
+ if ((fir::isa_trivial(varType) || fir::isa_char(varType) ||
+ fir::isa_builtin_cptr_type(varType)) &&
+ exists(defMap::VariableCategory::Scalar))
+ return defaultMaps[defMap::VariableCategory::Scalar];
+
+ if (fir::isPointerType(varType) &&
+ exists(defMap::VariableCategory::Pointer))
+ return defaultMaps[defMap::VariableCategory::Pointer];
+
+ if (fir::isAllocatableType(varType) &&
+ exists(defMap::VariableCategory::Allocatable))
+ return defaultMaps[defMap::VariableCategory::Allocatable];
+
+ if (fir::isa_aggregate(varType) &&
+ exists(defMap::VariableCategory::Aggregate)) {
+ return defaultMaps[defMap::VariableCategory::Aggregate];
+ }
+
+ return defMap::ImplicitBehavior::Default;
+ };
+
+ auto getImplicitMapTypeAndKind = [&](mlir::Type varType,
+ const semantics::Symbol &sym) {
+ using defMap = clause::Defaultmap;
+ llvm::omp::OpenMPOffloadMappingFlags mapFlag =
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
+
+ auto implicitBehaviour = getDefaultmapIfPresent(varType);
+ if (implicitBehaviour == defMap::ImplicitBehavior::Default) {
+ mlir::omp::VariableCaptureKind captureKind =
+ mlir::omp::VariableCaptureKind::ByRef;
+
+ // If a variable is specified in declare target link and if device
+ // type is not specified as `nohost`, it needs to be mapped tofrom
+ mlir::ModuleOp mod = firOpBuilder.getModule();
+ mlir::Operation *op = mod.lookupSymbol(converter.mangleName(sym));
+ auto declareTargetOp =
+ llvm::dyn_cast_if_present<mlir::omp::DeclareTargetInterface>(op);
+ if (declareTargetOp && declareTargetOp.isDeclareTarget()) {
+ if (declareTargetOp.getDeclareTargetCaptureClause() ==
+ mlir::omp::DeclareTargetCaptureClause::link &&
+ declareTargetOp.getDeclareTargetDeviceType() !=
+ mlir::omp::DeclareTargetDeviceType::nohost) {
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
+ }
+ } else if (fir::isa_trivial(varType) || fir::isa_char(varType)) {
+ // Scalars behave as if they were "firstprivate".
+ // TODO: Handle objects that are shared/lastprivate or were listed
+ // in an in_reduction clause.
+ if (isLiteralType(varType)) {
+ captureKind = mlir::omp::VariableCaptureKind::ByCopy;
+ } else {
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
+ }
+ } else if (!fir::isa_builtin_cptr_type(varType)) {
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
+ }
+ return std::make_pair(mapFlag, captureKind);
+ }
+
+ switch (implicitBehaviour) {
+ case defMap::ImplicitBehavior::Alloc:
+ return std::make_pair(llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
+ mlir::omp::VariableCaptureKind::ByRef);
+ break;
+ case defMap::ImplicitBehavior::Firstprivate:
+ case defMap::ImplicitBehavior::None:
+ TODO(loc, "Firstprivate and None are currently unsupported defaultmap "
+ "behaviour");
+ break;
+ case defMap::ImplicitBehavior::From:
+ return std::make_pair(mapFlag |=
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM,
+ mlir::omp::VariableCaptureKind::ByRef);
+ break;
+ case defMap::ImplicitBehavior::Present:
+ return std::make_pair(
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT,
+ mlir::omp::VariableCaptureKind::ByRef);
+ break;
+ case defMap::ImplicitBehavior::To:
+ return std::make_pair(
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
+ (fir::isa_trivial(varType) || fir::isa_char(varType))
+ ? mlir::omp::VariableCaptureKind::ByCopy
+ : mlir::omp::VariableCaptureKind::ByRef);
+ break;
+ case defMap::ImplicitBehavior::Tofrom:
+ return std::make_pair(mapFlag |=
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM |
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
+ mlir::omp::VariableCaptureKind::ByRef);
+ break;
+ case defMap::ImplicitBehavior::Default:
+ llvm_unreachable(
+ "Implicit None Behaviour Should Have Been Handled Earlier");
+ break;
+ }
+
+ return std::make_pair(mapFlag |=
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM |
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
+ mlir::omp::VariableCaptureKind::ByRef);
+ };
+
// 5.8.1 Implicit Data-Mapping Attribute Rules
// The following code follows the implicit data-mapping rules to map all the
// symbols used inside the region that do not have explicit data-environment
@@ -2327,62 +2454,32 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
fir::factory::AddrAndBoundsInfo info =
Fortran::lower::getDataOperandBaseAddr(
converter, firOpBuilder, sym, converter.getCurrentLocation());
- llvm::SmallVector<mlir::Value> bounds =
- fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
- mlir::omp::MapBoundsType>(
- firOpBuilder, info, dataExv,
- semantics::IsAssumedSizeArray(sym.GetUltimate()),
- converter.getCurrentLocation());
-
- llvm::omp::OpenMPOffloadMappingFlags mapFlag =
- llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
- mlir::omp::VariableCaptureKind captureKind =
- mlir::omp::VariableCaptureKind::ByRef;
mlir::Value baseOp = info.rawInput;
mlir::Type eleType = baseOp.getType();
if (auto refType = mlir::dyn_cast<fir::ReferenceType>(baseOp.getType()))
eleType = refType.getElementType();
- // If a variable is specified in declare target link and if device
- // type is not specified as `nohost`, it needs to be mapped tofrom
- mlir::ModuleOp mod = firOpBuilder.getModule();
- mlir::Operation *op = mod.lookupSymbol(converter.mangleName(sym));
- auto declareTargetOp =
- llvm::dyn_cast_if_present<mlir::omp::DeclareTargetInterface>(op);
- if (declareTargetOp && declareTargetOp.isDeclareTarget()) {
- if (declareTargetOp.getDeclareTargetCaptureClause() ==
- mlir::omp::DeclareTargetCaptureClause::link &&
- declareTargetOp.getDeclareTargetDeviceType() !=
- mlir::omp::DeclareTargetDeviceType::nohost) {
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
- }
- } else if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) {
- // Scalars behave as if they were "firstprivate".
- // TODO: Handle objects that are shared/lastprivate or were listed
- // in an in_reduction clause.
- if (isLiteralType(eleType)) {
- captureKind = mlir::omp::VariableCaptureKind::ByCopy;
- } else {
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
- }
- } else if (!fir::isa_builtin_cptr_type(eleType)) {
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
- }
- auto location =
- mlir::NameLoc::get(mlir::StringAttr::get(firOpBuilder.getContext(),
- sym.name().ToString()),
- baseOp.getLoc());
+ auto mapFlagAndKind = getImplicitMapTypeAndKind(eleType, sym);
+
+ llvm::SmallVector<mlir::Value> bounds =
+ fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
+ mlir::omp::MapBoundsType>(
+ firOpBuilder, info, dataExv,
+ semantics::IsAssumedSizeArray(sym.GetUltimate()),
+ converter.getCurrentLocation());
+ mlir::NameLoc::get(mlir::StringAttr::get(firOpBuilder.getContext(),
+ sym.name().ToString()),
+ baseOp.getLoc());
mlir::Value mapOp = createMapInfoOp(
- firOpBuilder, location, baseOp, /*varPtrPtr=*/mlir::Value{},
- name.str(), bounds, /*members=*/{},
+ firOpBuilder, converter.getCurrentLocation(), baseOp,
+ /*varPtrPtr=*/mlir::Value{}, name.str(), bounds, /*members=*/{},
/*membersIndex=*/mlir::ArrayAttr{},
static_cast<
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
- mapFlag),
- captureKind, baseOp.getType(), /*partialMap=*/false, mapperId);
+ std::get<0>(mapFlagAndKind)),
+ std::get<1>(mapFlagAndKind), baseOp.getType(),
+ /*partialMap=*/false, mapperId);
clauseOps.mapVars.push_back(mapOp);
mapSyms.push_back(&sym);
@@ -3539,6 +3636,7 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
!std::holds_alternative<clause::Copyin>(clause.u) &&
!std::holds_alternative<clause::Copyprivate>(clause.u) &&
!std::holds_alternative<clause::Default>(clause.u) &&
+ !std::holds_alternative<clause::Defaultmap>(clause.u) &&
!std::holds_alternative<clause::Depend>(clause.u) &&
!std::holds_alternative<clause::Filter>(clause.u) &&
!std::holds_alternative<clause::Final>(clause.u) &&
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index e84abf87c1cb6..9f625379b54d6 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -668,7 +668,7 @@ TYPE_PARSER(construct<OmpMapClause>(
// [OpenMP 5.0]
// 2.19.7.2 defaultmap(implicit-behavior[:variable-category])
// implicit-behavior -> ALLOC | TO | FROM | TOFROM | FIRSRTPRIVATE | NONE |
-// DEFAULT
+// DEFAULT | PRESENT
// variable-category -> ALL | SCALAR | AGGREGATE | ALLOCATABLE | POINTER
TYPE_PARSER(construct<OmpDefaultmapClause>(
construct<OmpDefaultmapClause::ImplicitBehavior>(
@@ -679,7 +679,8 @@ TYPE_PARSER(construct<OmpDefaultmapClause>(
"FIRSTPRIVATE" >>
pure(OmpDefaultmapClause::ImplicitBehavior::Firstprivate) ||
"NONE" >> pure(OmpDefaultmapClause::ImplicitBehavior::None) ||
- "DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)),
+ "DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default) ||
+ "PRESENT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Present)),
maybe(":" >> nonemptyList(Parser<OmpDefaultmapClause::Modifier>{}))))
TYPE_PARSER(construct<OmpScheduleClause::Kind>(
diff --git a/flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90 b/flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90
new file mode 100644
index 0000000000000..0af2c7f5ea818
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90
@@ -0,0 +1,11 @@
+!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
+!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
+
+subroutine f00
+ implicit none
+ integer :: i
+ !CHECK: not yet implemented: Firstprivate and None are currently unsupported defaultmap behaviour
+ !$omp target defaultmap(firstprivate)
+ i = 10
+ !$omp end target
+ end
diff --git a/flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90 b/flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90
new file mode 100644
index 0000000000000..287eb4a9dfe8f
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90
@@ -0,0 +1,11 @@
+!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
+!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
+
+subroutine f00
+ implicit none
+ integer :: i
+ !CHECK: not yet implemented: Firstprivate and None are currently unsupported defaultmap behaviour
+ !$omp target defaultmap(none)
+ i = 10
+ !$omp end target
+end
diff --git a/flang/test/Lower/OpenMP/Todo/defaultmap-clause.f90 b/flang/test/Lower/OpenMP/Todo/defaultmap-clause.f90
deleted file mode 100644
index 062399d9a1944..0000000000000
--- a/flang/test/Lower/OpenMP/Todo/defaultmap-clause.f90
+++ /dev/null
@@ -1,8 +0,0 @@
-!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=45 -o - %s 2>&1 | FileCheck %s
-!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=45 -o - %s 2>&1 | FileCheck %s
-
-!CHECK: not yet implemented: DEFAULTMAP clause is not implemented yet
-subroutine f00
- !$omp target defaultmap(tofrom:scalar)
- !$omp end target
-end
diff --git a/flang/test/Lower/OpenMP/defaultmap.f90 b/flang/test/Lower/OpenMP/defaultmap.f90
new file mode 100644
index 0000000000000..89d86ac1b8cc9
--- /dev/null
+++ b/flang/test/Lower/OpenMP/defaultmap.f90
@@ -0,0 +1,105 @@
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+
+subroutine defaultmap_allocatable_present()
+ implicit none
+ integer, dimension(:...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/135226
More information about the flang-commits
mailing list