Skip to content

[Flang][OpenMP] Initial defaultmap implementation #135226

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 1 commit into
base: main
Choose a base branch
from

Conversation

agozillon
Copy link
Contributor

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).

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.
@llvmbot
Copy link
Member

llvmbot commented Apr 10, 2025

@llvm/pr-subscribers-flang-fir-hlfir
@llvm/pr-subscribers-flang-openmp

@llvm/pr-subscribers-flang-parser

Author: None (agozillon)

Changes

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 --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]

@llvmbot
Copy link
Member

llvmbot commented Apr 10, 2025

@llvm/pr-subscribers-offload

Author: None (agozillon)

Changes

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 --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]

@agozillon
Copy link
Contributor Author

Small ping on this for reviews if at all possible, thank you very much ahead of time :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:fir-hlfir flang:openmp flang:parser flang Flang issues not falling into any other category offload
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants