[flang-commits] [flang] [llvm] [Flang][OpenMP] Prevent unrequired implicit maps for private variables on composite directives (PR #217121)

via flang-commits flang-commits at lists.llvm.org
Fri Oct 23 16:07:23 PDT 2026


https://github.com/agozillon updated https://github.com/llvm/llvm-project/pull/217121

>From 0b0f7a223cb77665d9cff33f6222ae1dccb31aaa Mon Sep 17 00:00:00 2001
From: agozillon <Andrew.Gozillon at amd.com>
Date: Wed, 26 Aug 2026 13:37:55 -0500
Subject: [PATCH 1/3] [Flang][OpenMP] Prevent unrequired implicit maps for
 private variables on composite directives

Currently we are emitting implicit maps for private variables on composite directives, these maps are unrequired as the private clause does not require filling from the original clause item. They're default allocated and a user must assign to them.

The problem is that at the point we are processing implicit maps on the target region, the private symbol has not been marked appropriately for the DataSharingProcessor to connect the dots that it belongs to the target region (and technically other components of the composite directive) and not just the leaf construct. So, the DataSharingProcessor doesn't gather the symbol, and the implicit mapper generates a map as the symbol isn't in the privatized symbol list gathered for the directive.

The approach taken in this patch is to perform a pseudo privatization at the target level, skipping implicit maps for certain types and creating an intermediate allocation to avoid IFA issues with the nested private clauses pointing external to the target region.
---
 flang/include/flang/Lower/OpenMP/Clauses.h    | 110 ++++
 flang/include/flang/Utils/OpenMP.h            |  22 +-
 flang/lib/Lower/OpenMP/OpenMP.cpp             | 301 ++++++++++-
 flang/lib/Utils/OpenMP.cpp                    |  39 +-
 .../target-composite-private-edge-cases.f90   | 144 ++++++
 ...target-composite-private-host-eval-map.f90 |  61 +++
 .../target-composite-private-unified.f90      | 469 ++++++++++++++++++
 .../OpenMP/target-nested-private-unified.f90  | 304 ++++++++++++
 .../Lower/OpenMP/target-nested-private.f90    |  67 +++
 .../Lower/OpenMP/target-parallel-private.f90  |   2 +-
 flang/test/Lower/OpenMP/target-scope.f90      |   9 +-
 .../Lower/OpenMP/target-teams-private.f90     |   2 +-
 ...target-composite-private-host-eval-map.f90 |  62 +++
 13 files changed, 1569 insertions(+), 23 deletions(-)
 create mode 100644 flang/test/Lower/OpenMP/target-composite-private-edge-cases.f90
 create mode 100644 flang/test/Lower/OpenMP/target-composite-private-host-eval-map.f90
 create mode 100644 flang/test/Lower/OpenMP/target-composite-private-unified.f90
 create mode 100644 flang/test/Lower/OpenMP/target-nested-private-unified.f90
 create mode 100644 flang/test/Lower/OpenMP/target-nested-private.f90
 create mode 100644 offload/test/offloading/fortran/target-composite-private-host-eval-map.f90

diff --git a/flang/include/flang/Lower/OpenMP/Clauses.h b/flang/include/flang/Lower/OpenMP/Clauses.h
index fb5b5d50670f72..7299ad3945fb27 100644
--- a/flang/include/flang/Lower/OpenMP/Clauses.h
+++ b/flang/include/flang/Lower/OpenMP/Clauses.h
@@ -9,6 +9,7 @@
 #define FORTRAN_LOWER_OPENMP_CLAUSES_H
 
 #include "flang/Evaluate/expression.h"
+#include "flang/Evaluate/tools.h"
 #include "flang/Evaluate/type.h"
 #include "flang/Parser/parse-tree.h"
 #include "flang/Semantics/expression.h"
@@ -20,6 +21,7 @@
 #include "llvm/Frontend/OpenMP/OMP.h.inc"
 
 #include <optional>
+#include <tuple>
 #include <type_traits>
 #include <utility>
 
@@ -392,6 +394,114 @@ struct Clause : public ClauseBase {
   parser::CharBlock source;
 };
 
+namespace detail {
+template <typename T, typename = void>
+struct HasClauseWrapperTrait : std::false_type {};
+template <typename T>
+struct HasClauseWrapperTrait<T, std::void_t<typename T::WrapperTrait>>
+    : T::WrapperTrait {};
+
+template <typename T, typename = void>
+struct HasClauseTupleTrait : std::false_type {};
+template <typename T>
+struct HasClauseTupleTrait<T, std::void_t<typename T::TupleTrait>>
+    : T::TupleTrait {};
+
+template <typename T, typename = void>
+struct HasClauseUnionTrait : std::false_type {};
+template <typename T>
+struct HasClauseUnionTrait<T, std::void_t<typename T::UnionTrait>>
+    : T::UnionTrait {};
+
+template <typename T>
+struct IsStdOptional : std::false_type {};
+template <typename T>
+struct IsStdOptional<std::optional<T>> : std::true_type {};
+
+template <typename T>
+struct IsStdTuple : std::false_type {};
+template <typename... Ts>
+struct IsStdTuple<std::tuple<Ts...>> : std::true_type {};
+} // namespace detail
+
+template <typename T, typename Callback>
+bool visitSymbolsInClausePayload(const T &value, Callback callback);
+
+template <typename Callback>
+bool visitSymbolsInClausePayload(const SomeExpr &expr, Callback callback) {
+  for (semantics::SymbolRef ref : evaluate::CollectSymbols(expr))
+    if (callback(*ref))
+      return true;
+  return false;
+}
+
+template <typename Callback>
+bool visitSymbolsInClausePayload(const Object &object, Callback callback) {
+  if (const semantics::Symbol *sym = object.sym())
+    if (callback(*sym))
+      return true;
+
+  // Include references appearing in designators, such as array section bounds
+  // or subscripts in map/depend list items.
+  if (object.ref())
+    return visitSymbolsInClausePayload(*object.ref(), callback);
+
+  return false;
+}
+
+template <typename Callback>
+bool visitSymbolsInClausePayload(const ObjectList &objects, Callback callback) {
+  for (const Object &object : objects)
+    if (visitSymbolsInClausePayload(object, callback))
+      return true;
+  return false;
+}
+
+template <typename T, unsigned N, typename Callback>
+bool visitSymbolsInClausePayload(const llvm::SmallVector<T, N> &values,
+                                 Callback callback) {
+  for (const T &value : values)
+    if (visitSymbolsInClausePayload(value, callback))
+      return true;
+  return false;
+}
+
+template <typename T, typename Callback>
+bool visitSymbolsInClausePayload(const T &value, Callback callback) {
+  using U = llvm::remove_cvref_t<T>;
+
+  if constexpr (detail::IsStdOptional<U>::value) {
+    return value && visitSymbolsInClausePayload(*value, callback);
+  } else if constexpr (detail::IsStdTuple<U>::value) {
+    return std::apply(
+        [&](const auto &...tupleValues) {
+          return (visitSymbolsInClausePayload(tupleValues, callback) || ...);
+        },
+        value);
+  } else if constexpr (detail::HasClauseWrapperTrait<U>::value) {
+    return visitSymbolsInClausePayload(value.v, callback);
+  } else if constexpr (detail::HasClauseTupleTrait<U>::value) {
+    return visitSymbolsInClausePayload(value.t, callback);
+  } else if constexpr (detail::HasClauseUnionTrait<U>::value) {
+    return Fortran::common::visit(
+        [&](const auto &variantValue) {
+          return visitSymbolsInClausePayload(variantValue, callback);
+        },
+        value.u);
+  } else {
+    return false;
+  }
+}
+
+template <typename Callback>
+bool visitSymbolsInClause(const Clause &clause, Callback callback) {
+  return Fortran::common::visit(
+      [&](const auto &specificClause) {
+        return visitSymbolsInClausePayload(specificClause, callback);
+      },
+      clause.u);
+}
+
 template <typename Specific>
 Clause makeClause(llvm::omp::Clause id, Specific &&specific,
                   parser::CharBlock source = {}) {
diff --git a/flang/include/flang/Utils/OpenMP.h b/flang/include/flang/Utils/OpenMP.h
index 0cb77e25af9475..fb76cc184cd366 100644
--- a/flang/include/flang/Utils/OpenMP.h
+++ b/flang/include/flang/Utils/OpenMP.h
@@ -50,16 +50,28 @@ mlir::Value mapTemporaryValue(fir::FirOpBuilder &firOpBuilder,
     mlir::omp::TargetOp targetOp, mlir::Value val,
     llvm::StringRef name = "tmp.map");
 
+/// Select how to repair values used in a target region but defined above it.
+enum class RegionOutsiderHandling {
+  /// Try to clone memory-effect-free producers used by the target entry block,
+  /// and map remaining values through target map entries.
+  CloneOrMapEntryBlockUses,
+  /// Try to clone memory-effect-free producers used anywhere in the target
+  /// region. Do not create new maps; fail if an outsider cannot be cloned.
+  CloneWholeRegionUsesOnly,
+};
+
 /// For values used inside a target region but defined outside, either clone
-/// these value inside the target region or map them to the region. This
-/// function first tries to clone values (if they are defined by
-/// memory-effect-free ops, otherwise, the values are mapped.
+/// these values inside the target region or map them to the region.
 ///
 /// \param firOpBuilder - Operation builder.
 /// \param targetOp     - The target that needs to be extended by clones and/or
 /// maps.
-void cloneOrMapRegionOutsiders(
-    fir::FirOpBuilder &firOpBuilder, mlir::omp::TargetOp targetOp);
+/// \param handling     - Specifies whether uncloneable outsiders can be mapped,
+/// and which uses should be rewritten.
+void cloneOrMapRegionOutsiders(fir::FirOpBuilder &firOpBuilder,
+    mlir::omp::TargetOp targetOp,
+    RegionOutsiderHandling handling =
+        RegionOutsiderHandling::CloneOrMapEntryBlockUses);
 
 using RecordMemberMapperMangler =
     std::function<void(std::string &mapperId, llvm::StringRef memberName)>;
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index b529ca203cd617..8f6a01e933fe8f 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -69,6 +69,8 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Frontend/OpenMP/OMP.h"
 #include <atomic>
+#include <tuple>
+#include <type_traits>
 
 using namespace Fortran::lower::omp;
 using namespace Fortran::common::openmp;
@@ -2126,6 +2128,13 @@ static void genIntermediateCommonBlockAccessors(
   }
 }
 
+// Information about private list items that belong to a nested leaf construct
+// inside a target construct.
+struct TargetNestedPrivateInfo {
+  llvm::SmallVector<const semantics::Symbol *> syms;
+  bool innermostLeafIsTeams = false;
+};
+
 // This functions creates a block for the body of the targetOp's region. It adds
 // all the symbols present in mapSymbols as block arguments to this block.
 static void genBodyOfTargetOp(
@@ -2133,7 +2142,8 @@ static void genBodyOfTargetOp(
     semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
     mlir::omp::TargetOp &targetOp, const ObjectEntryBlockArgs &args,
     const mlir::Location &currentLocation, const ConstructQueue &queue,
-    ConstructQueue::const_iterator item, DataSharingProcessor &dsp) {
+    ConstructQueue::const_iterator item, DataSharingProcessor &dsp,
+    const TargetNestedPrivateInfo &targetNestedPrivateInfo) {
   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
   auto argIface = llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(*targetOp);
 
@@ -2180,6 +2190,14 @@ static void genBodyOfTargetOp(
   // Create the insertion point after the marker.
   firOpBuilder.setInsertionPointAfter(undefMarker.getDefiningOp());
 
+  // Materialize region-local copies for the private list items of inner leaf
+  // constructs (e.g. distribute) of a combined/composite target directive,
+  // with the intent of replacing a host to device data-mapping (map info
+  // emission). Teams already performs this materialization itself.
+  if (!targetNestedPrivateInfo.innermostLeafIsTeams)
+    for (const semantics::Symbol *sym : targetNestedPrivateInfo.syms)
+      converter.createHostAssociateVarClone(*sym, /*skipDefaultInit=*/false);
+
   bool immediatelyNestsTeams = false;
   if (std::next(item) != queue.end()) {
     immediatelyNestsTeams = llvm::omp::topTeamsSet.test(std::next(item)->id);
@@ -2204,6 +2222,15 @@ static void genBodyOfTargetOp(
     genNestedEvaluations(converter, eval);
   }
 
+  // When materializing arrays inside of the target region for composite
+  // directives with leaf-bound private clauses, we can end up with the
+  // constants populating the shape being bound to constants external to the
+  // target region. Perform a final clone-only repair to resolve these without
+  // introducing new maps after the target operation has already been created.
+  if (!targetNestedPrivateInfo.syms.empty())
+    cloneOrMapRegionOutsiders(firOpBuilder, targetOp,
+                              RegionOutsiderHandling::CloneWholeRegionUsesOnly);
+
   dsp.processStep2(targetOp, /*isLoop=*/false);
 }
 
@@ -4007,6 +4034,254 @@ static void collectSymbolsWithDynamicSubstring(
   symbolsWithDynamicSubstring = visitor.symbolsWithDynamicSubstring;
 }
 
+// Reverse search a composite/combined directive and return the innermost leaf
+// carrying a private clause. The OpenMP specification dictates that the first
+// leaf that can legally have a private clause becomes the owner, except when an
+// OpenMP 6.0+ directive-name-modifier explicitly attaches clauses to another
+// leaf or construct in the compound directive.
+//
+// TODO: Extend handling to support directive-name-modifier usage placing
+// private clauses on multiple leaf nodes or constituent constructs.
+static ConstructQueue::const_iterator
+findInnermostPrivateLeaf(ConstructQueue::const_iterator begin,
+                         const ConstructQueue &queue) {
+  auto hasPrivate = [](ConstructQueue::const_iterator it) {
+    return llvm::any_of(it->clauses, [](const Clause &clause) {
+      return std::holds_alternative<clause::Private>(clause.u);
+    });
+  };
+  for (auto it = queue.end(); it != begin;) {
+    --it;
+    if (hasPrivate(it))
+      return it;
+  }
+  return queue.end();
+}
+
+static List<Clause>
+getOpenMPConstructClauses(const parser::OpenMPConstruct &ompEval,
+                          semantics::SemanticsContext &semaCtx) {
+  List<Clause> clauses;
+  const parser::OmpClauseList *beginClauseList{nullptr};
+  const parser::OmpClauseList *endClauseList{nullptr};
+
+  common::visit(
+      [&](const auto &construct) {
+        using Type = llvm::remove_cvref_t<decltype(construct)>;
+        if constexpr (std::is_same_v<Type, parser::OmpBlockConstruct> ||
+                      std::is_same_v<Type, parser::OpenMPLoopConstruct>) {
+          beginClauseList = &construct.BeginDir().Clauses();
+          if (auto &endSpec{construct.EndDir()})
+            endClauseList = &endSpec->Clauses();
+        }
+      },
+      ompEval.u);
+
+  if (!beginClauseList)
+    return clauses;
+
+  clauses.append(makeClauses(*beginClauseList, semaCtx));
+
+  if (endClauseList)
+    clauses.append(makeClauses(*endClauseList, semaCtx));
+
+  return clauses;
+}
+
+static bool isSymbolUsedInClauseRange(const semantics::Symbol &target,
+                                      ConstructQueue::const_iterator begin,
+                                      ConstructQueue::const_iterator end,
+                                      bool ignorePrivateAndMap) {
+  const semantics::Symbol &ultimateTarget = target.GetUltimate();
+
+  for (ConstructQueue::const_iterator it = begin; it != end; ++it) {
+    for (const Clause &clause : it->clauses) {
+      // Do not consider private itself. Also do not consider map clauses here:
+      // explicit target-level maps are already accounted for via mapObjects,
+      // and construct decomposition may synthesize map-like clauses for nested
+      // private list items.
+      if (ignorePrivateAndMap &&
+          (clause.id == llvm::omp::Clause::OMPC_private ||
+           clause.id == llvm::omp::Clause::OMPC_map))
+        continue;
+
+      if (visitSymbolsInClause(clause, [&](const semantics::Symbol &sym) {
+            return sym.GetUltimate() == ultimateTarget;
+          }))
+        return true;
+    }
+  }
+  return false;
+}
+
+// Verify if it is safe to drop the map and materialize a target-local clone.
+// Certain cases still require a map to be OpenMP specification compliant:
+//
+//  Allocatable -
+//    1) If the status is unallocated, the private allocatable is unallocated
+//    2) If the allocation status is allocated, the private allocatable is
+//       allocated
+//    3) If it is an array, the allocatable's shape and bounds are preserved.
+//  Pointer - The initial status of a private pointer is undefined.
+//  Other - If the type of the list item has default initialization, the new
+//    list item has default initialization. Otherwise, it is undefined.
+//
+// From the above list, it is currently fine to drop maps and materialize clones
+// for scalars, pointers, and constant arrays. Their creation does not require
+// dynamic extent/shape/allocation-status values defined outside the target
+// region. Types that still need a map just to populate the initial state are
+// allocatables, derived types with allocatable or pointer ultimate components,
+// assumed-shape arrays, automatic arrays, and common block members. Currently
+// we leave these as they were before, but in the future we can minimize the
+// mapping by sending across exactly what is required to be specification
+// compliant.
+static bool isTargetLocalCloneable(const semantics::Symbol &sym,
+                                   semantics::SemanticsContext &semaCtx) {
+  const semantics::Symbol &ult = sym.GetUltimate();
+
+  if (Fortran::semantics::FindCommonBlockContaining(ult))
+    return false;
+
+  if (semantics::IsAllocatable(ult))
+    return false;
+
+  if (const semantics::DeclTypeSpec *declType = ult.GetType())
+    if (const semantics::DerivedTypeSpec *derived = declType->AsDerived())
+      if (semantics::FindAllocatableUltimateComponent(*derived) ||
+          semantics::FindPointerUltimateComponent(*derived))
+        return false;
+
+  // A private pointer's initial status is undefined, so it can be materialized
+  // with the correct type. Other non-scalar private list items must have
+  // constant extents and shape so their storage can be created target-locally.
+  if (ult.Rank() > 0 && !semantics::IsPointer(ult)) {
+    evaluate::FoldingContext &foldingContext = semaCtx.foldingContext();
+    std::optional<evaluate::Shape> shape =
+        evaluate::GetShape(foldingContext, ult);
+    std::optional<evaluate::ConstantSubscripts> extents =
+        evaluate::AsConstantExtents(foldingContext, shape);
+    if (!extents || evaluate::HasNegativeExtent(*extents))
+      return false;
+  }
+  return true;
+}
+
+static bool isExplicitlyMapped(const semantics::Symbol &sym,
+                               llvm::ArrayRef<Object> mapObjects) {
+  const semantics::Symbol &ult = sym.GetUltimate();
+  return llvm::any_of(mapObjects, [&](const Object &object) {
+    return object.sym() && object.sym()->GetUltimate() == ult;
+  });
+}
+
+static bool isAlreadyPrivatizedOnTarget(const semantics::Symbol &sym,
+                                        const DataSharingProcessor &dsp) {
+  const semantics::Symbol &ult = sym.GetUltimate();
+  return llvm::any_of(dsp.getAllSymbolsToPrivatize(),
+                      [&](const semantics::Symbol *priv) {
+                        return priv->GetUltimate() == ult;
+                      });
+}
+
+static void collectTargetNestedPrivateSymsFromLeaf(
+    ConstructQueue::const_iterator leaf, ConstructQueue::const_iterator begin,
+    ConstructQueue::const_iterator end, llvm::ArrayRef<Object> mapObjects,
+    const DataSharingProcessor &dsp, bool excludePrivatizedSyms,
+    semantics::SemanticsContext &semaCtx, TargetNestedPrivateInfo &result) {
+  result.innermostLeafIsTeams = llvm::omp::topTeamsSet.test(leaf->id);
+
+  for (const Clause &clause : leaf->clauses) {
+    if (const auto *priv = std::get_if<clause::Private>(&clause.u)) {
+      for (const Object &object : priv->v) {
+        const semantics::Symbol *sym = object.sym();
+        if (!sym)
+          continue;
+        if (isExplicitlyMapped(*sym, mapObjects))
+          continue;
+        if (excludePrivatizedSyms && isAlreadyPrivatizedOnTarget(*sym, dsp))
+          continue;
+        if (isSymbolUsedInClauseRange(*sym, begin, end,
+                                      /*ignorePrivateAndMap=*/true))
+          continue;
+        if (!isTargetLocalCloneable(*sym, semaCtx))
+          continue;
+        result.syms.push_back(sym);
+      }
+    }
+  }
+}
+
+static bool collectTargetNestedPrivateSymsFromQueue(
+    ConstructQueue::const_iterator begin, const ConstructQueue &queue,
+    llvm::ArrayRef<Object> mapObjects, const DataSharingProcessor &dsp,
+    bool excludePrivatizedSyms, semantics::SemanticsContext &semaCtx,
+    TargetNestedPrivateInfo &result) {
+  ConstructQueue::const_iterator leaf = findInnermostPrivateLeaf(begin, queue);
+  if (leaf == queue.end())
+    return false;
+
+  collectTargetNestedPrivateSymsFromLeaf(leaf, begin, queue.end(), mapObjects,
+                                         dsp, excludePrivatizedSyms, semaCtx,
+                                         result);
+  return true;
+}
+
+// Discover `private` list items on the inner leaf construct of a
+// combined/composite target construct, e.g. "s" in
+// `target teams distribute private(s)`. These symbols are not privatized on the
+// target itself and, without intervention, would usually be implicitly mapped.
+// Collect them so implicit-map generation can skip unneeded maps and target
+// body generation can materialize region-local replacements when needed.
+static TargetNestedPrivateInfo collectTargetNestedPrivateSyms(
+    mlir::ModuleOp modOp, semantics::SemanticsContext &semaCtx,
+    lower::pft::Evaluation &eval, ConstructQueue::const_iterator item,
+    const ConstructQueue &queue, llvm::ArrayRef<Object> mapObjects,
+    const DataSharingProcessor &dsp) {
+  TargetNestedPrivateInfo result;
+
+  ConstructQueue::const_iterator next = std::next(item);
+  if (next != queue.end() &&
+      collectTargetNestedPrivateSymsFromQueue(next, queue, mapObjects, dsp,
+                                              /*excludePrivatizedSyms=*/true,
+                                              semaCtx, result))
+    return result;
+
+  lower::pft::Evaluation *nestedEval = extractOnlyOmpNestedEval(eval);
+  if (!nestedEval)
+    return result;
+
+  const auto &ompEval = nestedEval->get<parser::OpenMPConstruct>();
+  parser::OmpDirectiveName nestedName =
+      parser::omp::GetOmpDirectiveName(ompEval);
+  List<Clause> nestedClauses = getOpenMPConstructClauses(ompEval, semaCtx);
+  if (!llvm::any_of(nestedClauses, [](const Clause &clause) {
+        return std::holds_alternative<clause::Private>(clause.u);
+      }))
+    return result;
+
+  ConstructQueue nestedQueue{buildConstructQueue(modOp, semaCtx, *nestedEval,
+                                                 nestedName.source,
+                                                 nestedName.v, nestedClauses)};
+
+  TargetNestedPrivateInfo nestedResult;
+  collectTargetNestedPrivateSymsFromQueue(
+      nestedQueue.begin(), nestedQueue, mapObjects, dsp,
+      /*excludePrivatizedSyms=*/false, semaCtx, nestedResult);
+
+  // If the target already had decomposed leaf constructs (e.g.
+  // target -> teams), only optimize through an immediately nested construct
+  // when the intervening leaves do not mention the candidate symbol in any
+  // clause. This avoids suppressing a target map needed by an intervening data
+  // environment.
+  if (next != queue.end())
+    llvm::erase_if(nestedResult.syms, [&](const semantics::Symbol *sym) {
+      return isSymbolUsedInClauseRange(*sym, next, queue.end(),
+                                       /*ignorePrivateAndMap=*/false);
+    });
+
+  return nestedResult;
+}
+
 static mlir::omp::TargetOp
 genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
             lower::StatementContext &stmtCtx,
@@ -4101,6 +4376,16 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
   collectSymbolsWithDynamicSubstring(semaCtx, eval,
                                      symbolsWithDynamicSubstring);
 
+  // Collect private clause symbols on the innermost leaf that can legally own
+  // the clause for composite directives. For example, in
+  // `target teams distribute private(s)`, "s" belongs to the distribute
+  // directive and not the target region. These symbols can skip be used to
+  // skip unneeded target implicit maps.
+  TargetNestedPrivateInfo targetNestedPrivateInfo =
+      collectTargetNestedPrivateSyms(converter.getFirOpBuilder().getModule(),
+                                     semaCtx, eval, item, queue, mapObjects,
+                                     dsp);
+
   // 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
@@ -4155,6 +4440,18 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
     if (sym.GetUltimate().test(semantics::Symbol::Flag::OmpGroupPrivate))
       return;
 
+    // Skip mapping of symbols that appear in private clauses of composite
+    // directive leaf nodes. For example, in
+    // `target teams distribute private(s)`, "s" does not need a map because all
+    // user-level uses are privatized and do not require a data transfer in most
+    // cases. Assumed-shape arrays are an exception because their shape is
+    // needed to create the private copy.
+    if (llvm::any_of(
+            targetNestedPrivateInfo.syms, [&](const semantics::Symbol *s) {
+              return s == &sym || s->GetUltimate() == sym.GetUltimate();
+            }))
+      return;
+
     if (!isDuplicateMappedSymbol(sym, dsp.getAllSymbolsToPrivatize(),
                                  hasDeviceAddrObjects, mapObjects,
                                  isDevicePtrObjects)) {
@@ -4317,7 +4614,7 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
   args.priv.vars = clauseOps.privateVars;
 
   genBodyOfTargetOp(converter, symTable, semaCtx, eval, targetOp, args, loc,
-                    queue, item, dsp);
+                    queue, item, dsp, targetNestedPrivateInfo);
 
   // Remove the host_eval information structure created for this target region.
   if (!isTargetDevice)
diff --git a/flang/lib/Utils/OpenMP.cpp b/flang/lib/Utils/OpenMP.cpp
index aa5ef994252f76..0a8c5bca578665 100644
--- a/flang/lib/Utils/OpenMP.cpp
+++ b/flang/lib/Utils/OpenMP.cpp
@@ -18,6 +18,8 @@
 #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
 #include "mlir/Transforms/RegionUtils.h"
 
+#include <cassert>
+
 namespace Fortran::utils::openmp {
 std::string getCanonicalDefaultDeclareMapperName(fir::RecordType recordType) {
   auto appendKinds = [](std::string &name, llvm::ArrayRef<std::int64_t> kinds) {
@@ -164,14 +166,28 @@ mlir::Value mapTemporaryValue(fir::FirOpBuilder &firOpBuilder,
   return loadOp.getResult();
 }
 
-void cloneOrMapRegionOutsiders(
-    fir::FirOpBuilder &firOpBuilder, mlir::omp::TargetOp targetOp) {
+void cloneOrMapRegionOutsiders(fir::FirOpBuilder &firOpBuilder,
+    mlir::omp::TargetOp targetOp, RegionOutsiderHandling handling) {
+  const bool canEmitMaps =
+      handling == RegionOutsiderHandling::CloneOrMapEntryBlockUses;
+  const bool rewriteWholeRegion =
+      handling == RegionOutsiderHandling::CloneWholeRegionUsesOnly;
   mlir::Region &region = targetOp.getRegion();
   mlir::Block *entryBlock = &region.getBlocks().front();
 
+  auto replace = [canEmitMaps, rewriteWholeRegion, entryBlock, &region](
+                     mlir::OpOperand &use) {
+    if (canEmitMaps)
+      return use.getOwner()->getBlock() == entryBlock;
+    if (rewriteWholeRegion)
+      return region.findAncestorOpInRegion(*use.getOwner()) != nullptr;
+    llvm_unreachable("unknown target region outsider repair mode");
+  };
+
   llvm::SetVector<mlir::Value> valuesDefinedAbove;
   mlir::getUsedValuesDefinedAbove(region, valuesDefinedAbove);
   while (!valuesDefinedAbove.empty()) {
+    bool madeProgress = false;
     for (mlir::Value val : valuesDefinedAbove) {
       mlir::Operation *valOp = val.getDefiningOp();
 
@@ -184,23 +200,26 @@ void cloneOrMapRegionOutsiders(
           !mlir::isa<fir::BoxDimsOp>(valOp)) {
         mlir::Operation *clonedOp = valOp->clone();
         entryBlock->push_front(clonedOp);
-
-        auto replace = [entryBlock](mlir::OpOperand &use) {
-          return use.getOwner()->getBlock() == entryBlock;
-        };
+        madeProgress = true;
 
         valOp->getResults().replaceUsesWithIf(clonedOp->getResults(), replace);
         valOp->replaceUsesWithIf(clonedOp, replace);
-      } else {
+      } else if (canEmitMaps) {
         mlir::Value mappedTemp = mapTemporaryValue(firOpBuilder, targetOp, val,
             /*name=*/{});
-        val.replaceUsesWithIf(mappedTemp, [entryBlock](mlir::OpOperand &use) {
-          return use.getOwner()->getBlock() == entryBlock;
-        });
+        madeProgress = true;
+        val.replaceUsesWithIf(mappedTemp, replace);
       }
     }
     valuesDefinedAbove.clear();
     mlir::getUsedValuesDefinedAbove(region, valuesDefinedAbove);
+
+    if (!canEmitMaps && !valuesDefinedAbove.empty() && !madeProgress) {
+      assert(false &&
+          "failed to clone all values used in the target region but defined "
+          "above it");
+      break;
+    }
   }
 }
 
diff --git a/flang/test/Lower/OpenMP/target-composite-private-edge-cases.f90 b/flang/test/Lower/OpenMP/target-composite-private-edge-cases.f90
new file mode 100644
index 00000000000000..5b280a4ae74c23
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-composite-private-edge-cases.f90
@@ -0,0 +1,144 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+module target_composite_private_edge_types
+  type :: dt_ptr
+    integer, pointer :: p
+  end type
+end module
+
+subroutine target_parallel_do_private_if(n, out)
+  integer :: n, out, i
+  out = 0
+  !$omp target parallel do private(n) if(n > 0) map(tofrom: out)
+  do i = 1, 4
+    n = i
+    out = out + n
+  end do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_parallel_do_private_if
+! CHECK: omp.map.info {{.*}} name("out")
+! CHECK: omp.map.info {{.*}} name("n")
+! CHECK: omp.map.info {{.*}} name("i")
+! CHECK: omp.target
+
+subroutine target_parallel_do_private_schedule(n, out)
+  integer :: n, out, i
+  out = 0
+  !$omp target parallel do private(n) schedule(static, n) map(tofrom: out)
+  do i = 1, 4
+    n = i
+    out = out + n
+  end do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_parallel_do_private_schedule
+! CHECK: omp.map.info {{.*}} name("out")
+! CHECK: omp.map.info {{.*}} name("n")
+! CHECK: omp.map.info {{.*}} name("i")
+! CHECK: omp.target
+
+subroutine target_teams_distribute_parallel_do_private(s, n, out)
+  integer :: s, n, out, i
+  out = 0
+  !$omp target teams distribute parallel do private(s) map(tofrom: out)
+  do i = 1, n
+    s = i
+    out = out + s
+  end do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_teams_distribute_parallel_do_private
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK: omp.map.info {{.*}} name("out")
+! CHECK: omp.map.info {{.*}} name("i")
+! CHECK: omp.map.info {{.*}} name("n")
+! CHECK: omp.target
+
+subroutine target_parallel_do_private_derived_pointer()
+  use target_composite_private_edge_types
+  type(dt_ptr) :: d
+  integer, target :: x
+  integer :: i
+  d%p => x
+  !$omp target parallel do private(d)
+  do i = 1, 4
+    if (associated(d%p)) d%p = i
+  end do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_parallel_do_private_derived_pointer
+! CHECK: omp.map.info {{.*}} name("d")
+! CHECK: omp.target
+
+subroutine target_parallel_do_private_common(out)
+  integer :: out, i, c
+  common /blk/ c
+  out = 0
+  !$omp target parallel do private(c) map(tofrom: out)
+  do i = 1, 4
+    c = i
+    out = out + c
+  end do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_parallel_do_private_common
+! CHECK: omp.map.info {{.*}} name("out")
+! CHECK: omp.map.info {{.*}} name("c")
+! CHECK: omp.target
+
+subroutine target_parallel_do_private_array_shape()
+  integer :: i, arr(4), out
+  out = 0
+  !$omp target parallel do private(arr) map(tofrom: out)
+  do i = 1, 4
+    arr(i) = i
+    out = out + arr(i)
+  end do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_parallel_do_private_array_shape
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK: omp.map.info {{.*}} name("out")
+! CHECK: omp.target
+! CHECK: fir.alloca !fir.array<4xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_parallel_do_private_array_shapeEarr"}
+! CHECK: omp.wsloop private(
+! CHECK-SAME: @_QFtarget_parallel_do_private_array_shapeEarr_private_4xi32
+
+subroutine target_teams_nested_parallel_private(s, out)
+  integer :: s, out
+  out = 0
+  !$omp target teams map(tofrom: out)
+    !$omp parallel private(s)
+      s = 1
+      out = out + s
+    !$omp end parallel
+  !$omp end target teams
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_teams_nested_parallel_private
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK: omp.map.info {{.*}} name("out")
+! CHECK: omp.target
+! CHECK: omp.teams
+! CHECK: omp.parallel private(
+! CHECK-SAME: @_QFtarget_teams_nested_parallel_privateEs_private_i32
+
+subroutine target_teams_nested_parallel_private_thread_limit(s, out)
+  integer :: s, out
+  out = 0
+  !$omp target teams thread_limit(s) map(tofrom: out)
+    !$omp parallel private(s)
+      s = 1
+      out = out + s
+    !$omp end parallel
+  !$omp end target teams
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_teams_nested_parallel_private_thread_limit
+! CHECK: omp.map.info {{.*}} name("out")
+! CHECK: omp.map.info {{.*}} name("s")
+! CHECK: omp.target
+! CHECK: omp.teams
+! CHECK: omp.parallel private(
+! CHECK-SAME: @_QFtarget_teams_nested_parallel_private_thread_limitEs_private_i32
diff --git a/flang/test/Lower/OpenMP/target-composite-private-host-eval-map.f90 b/flang/test/Lower/OpenMP/target-composite-private-host-eval-map.f90
new file mode 100644
index 00000000000000..a48c9963b77c03
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-composite-private-host-eval-map.f90
@@ -0,0 +1,61 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+subroutine target_parallel_do_private_num_threads(n, out)
+  integer :: n, out, i
+  out = 0
+  !$omp target parallel do private(n) num_threads(n) map(tofrom: out)
+  do i = 1, 4
+    n = i
+    out = out + n
+  end do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_parallel_do_private_num_threads
+! CHECK: %[[N_VAL:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+! CHECK: %[[OUT_MAP:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("out")
+! CHECK: %[[N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
+! CHECK: %[[I_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("i")
+! CHECK: omp.target kernel_type(spmd) host_eval({{.*}}, %[[N_VAL]] -> %[[N_HOST_ARG:arg[0-9]+]] : {{.*}}) map_entries(%[[OUT_MAP]] -> %{{.*}}, %[[N_MAP]] -> %[[N_MAP_ARG:arg[0-9]+]], %[[I_MAP]] -> %{{.*}} : {{.*}}) {
+! CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %[[N_MAP_ARG]] {uniq_name = "_QFtarget_parallel_do_private_num_threadsEn"}
+! CHECK: omp.parallel num_threads(%[[N_HOST_ARG]] : i32) {
+! CHECK: omp.wsloop private({{.*}}@_QFtarget_parallel_do_private_num_threadsEn_private_i32 %[[N_DECL]]#0 -> %arg{{[0-9]+}}
+
+subroutine target_teams_distribute_private_thread_limit(n, out)
+  integer :: n, out, i
+  out = 0
+  !$omp target teams distribute private(n) thread_limit(n) map(tofrom: out)
+  do i = 1, 4
+    n = i
+    out = out + n
+  end do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_teams_distribute_private_thread_limit
+! CHECK: %[[OUT_MAP:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("out")
+! CHECK: %[[N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
+! CHECK: %[[I_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("i")
+! CHECK: omp.target kernel_type(generic) host_eval({{.*}}) map_entries(%[[OUT_MAP]] -> %{{.*}}, %[[N_MAP]] -> %[[N_MAP_ARG:arg[0-9]+]], %[[I_MAP]] -> %{{.*}} : {{.*}}) {
+! CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %[[N_MAP_ARG]] {uniq_name = "_QFtarget_teams_distribute_private_thread_limitEn"}
+! CHECK: %[[N_LOAD:.*]] = fir.load %[[N_DECL]]#0 : !fir.ref<i32>
+! CHECK: omp.teams thread_limit(%[[N_LOAD]] : i32) {
+! CHECK: omp.distribute private({{.*}}@_QFtarget_teams_distribute_private_thread_limitEn_private_i32 %[[N_DECL]]#0 -> %arg{{[0-9]+}}
+
+subroutine target_teams_distribute_private_num_teams(n, out)
+  integer :: n, out, i
+  out = 0
+  !$omp target teams distribute private(n) num_teams(n) map(tofrom: out)
+  do i = 1, 4
+    n = i
+    out = out + n
+  end do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_teams_distribute_private_num_teams
+! CHECK: %[[N_VAL:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+! CHECK: %[[OUT_MAP:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("out")
+! CHECK: %[[N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
+! CHECK: %[[I_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("i")
+! CHECK: omp.target kernel_type(generic) host_eval({{.*}}, %[[N_VAL]] -> %[[N_HOST_ARG:arg[0-9]+]] : {{.*}}) map_entries(%[[OUT_MAP]] -> %{{.*}}, %[[N_MAP]] -> %[[N_MAP_ARG:arg[0-9]+]], %[[I_MAP]] -> %{{.*}} : {{.*}}) {
+! CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %[[N_MAP_ARG]] {uniq_name = "_QFtarget_teams_distribute_private_num_teamsEn"}
+! CHECK: omp.teams num_teams( to %[[N_HOST_ARG]] : i32) {
+! CHECK: omp.distribute private({{.*}}@_QFtarget_teams_distribute_private_num_teamsEn_private_i32 %[[N_DECL]]#0 -> %arg{{[0-9]+}}
diff --git a/flang/test/Lower/OpenMP/target-composite-private-unified.f90 b/flang/test/Lower/OpenMP/target-composite-private-unified.f90
new file mode 100644
index 00000000000000..1b0798d6d7561e
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-composite-private-unified.f90
@@ -0,0 +1,469 @@
+!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+module types
+  type :: dt
+    integer :: a
+    real :: b
+  end type
+  type :: dt_alloc
+    integer, allocatable :: a
+  end type
+  type :: dt_alloc_arr
+    integer, allocatable :: a(:)
+  end type
+end module
+
+subroutine target_teams(n, assumed)
+  use types
+  integer :: n, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target teams private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+  s = 1
+  !$omp end target teams
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_teams
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: %[[TEAMS_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TEAMS_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TEAMS_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
+! CHECK: %[[TEAMS_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
+! CHECK: %[[TEAMS_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
+! CHECK: %[[TEAMS_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TEAMS_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[TEAMS_ASSUMED_MEMBER]] {{.*}}) name("assumed")
+! CHECK: %[[TEAMS_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
+! CHECK: %[[TEAMS_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TEAMS_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TEAMS_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
+! CHECK: %[[TEAMS_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
+! CHECK: %[[TEAMS_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
+! CHECK: %[[TEAMS_AUTO_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("auto_arr")
+! CHECK: %[[TEAMS_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("")
+! CHECK: omp.target kernel_type(generic) map_entries(%[[TEAMS_ALLOC_MAP]] -> %{{.*}}, %[[TEAMS_DA_MAP]] -> %{{.*}}, %[[TEAMS_ASSUMED_MAP]] -> %{{.*}}, %[[TEAMS_ALLOC_ARR_MAP]] -> %{{.*}}, %[[TEAMS_DAA_MAP]] -> %{{.*}}, %[[TEAMS_AUTO_ARR_MAP]] -> %{{.*}}, %[[TEAMS_N_MAP]] -> %{{.*}}, %[[TEAMS_ALLOC_ATTACH]] -> %{{.*}}, %[[TEAMS_ASSUMED_ATTACH]] -> %{{.*}}, %[[TEAMS_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[TEAMS_ALLOC_MEMBER]] -> %{{.*}}, %[[TEAMS_ASSUMED_MEMBER]] -> %{{.*}}, %[[TEAMS_ALLOC_ARR_MEMBER]] -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) {
+! CHECK: hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teamsEalloc"}
+! CHECK: hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teamsEda"}
+! CHECK: hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teamsEassumed"}
+! CHECK: hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teamsEalloc_arr"}
+! CHECK: hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teamsEdaa"}
+! CHECK: hlfir.declare %arg{{[0-9]+}}(%{{.*}}) {uniq_name = "_QFtarget_teamsEauto_arr"}
+! CHECK: omp.teams {
+! CHECK: fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFtarget_teamsEs"}
+! CHECK: fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_teamsEarr"}
+! CHECK: fir.alloca !fir.box<!fir.heap<i32>> {bindc_name = "alloc", pinned, uniq_name = "_QFtarget_teamsEalloc"}
+! CHECK: fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFtarget_teamsEptr"}
+! CHECK: fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFtarget_teamsEd"}
+! CHECK: fir.alloca !fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}> {bindc_name = "da", pinned, uniq_name = "_QFtarget_teamsEda"}
+! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} {bindc_name = "assumed", pinned, uniq_name = "_QFtarget_teamsEassumed"}
+! CHECK: fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = "alloc_arr", pinned, uniq_name = "_QFtarget_teamsEalloc_arr"}
+! CHECK: fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_teamsEptr_arr"}
+! CHECK: fir.alloca !fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}> {bindc_name = "daa", pinned, uniq_name = "_QFtarget_teamsEdaa"}
+! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} {bindc_name = "auto_arr", pinned, uniq_name = "_QFtarget_teamsEauto_arr"}
+
+subroutine target_parallel(n, assumed)
+  use types
+  integer :: n, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target parallel private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+  s = 1
+  !$omp end target parallel
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_parallel
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: %[[PAR_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PAR_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[PAR_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
+! CHECK: %[[PAR_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
+! CHECK: %[[PAR_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
+! CHECK: %[[PAR_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PAR_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[PAR_ASSUMED_MEMBER]] {{.*}}) name("assumed")
+! CHECK: %[[PAR_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
+! CHECK: %[[PAR_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PAR_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[PAR_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
+! CHECK: %[[PAR_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
+! CHECK: %[[PAR_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
+! CHECK: %[[PAR_AUTO_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("auto_arr")
+! CHECK: %[[PAR_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("")
+! CHECK: omp.target kernel_type(generic) map_entries(%[[PAR_ALLOC_MAP]] -> %{{.*}}, %[[PAR_DA_MAP]] -> %{{.*}}, %[[PAR_ASSUMED_MAP]] -> %{{.*}}, %[[PAR_ALLOC_ARR_MAP]] -> %{{.*}}, %[[PAR_DAA_MAP]] -> %{{.*}}, %[[PAR_AUTO_ARR_MAP]] -> %{{.*}}, %[[PAR_N_MAP]] -> %{{.*}}, %[[PAR_ALLOC_ATTACH]] -> %{{.*}}, %[[PAR_ASSUMED_ATTACH]] -> %{{.*}}, %[[PAR_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[PAR_ALLOC_MEMBER]] -> %{{.*}}, %[[PAR_ASSUMED_MEMBER]] -> %{{.*}}, %[[PAR_ALLOC_ARR_MEMBER]] -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) {
+! CHECK: %[[PAR_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_parallelEalloc"}
+! CHECK: %[[PAR_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallelEda"}
+! CHECK: %[[PAR_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallelEassumed"}
+! CHECK: %[[PAR_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_parallelEalloc_arr"}
+! CHECK: %[[PAR_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallelEdaa"}
+! CHECK: %[[PAR_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) {uniq_name = "_QFtarget_parallelEauto_arr"}
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "da", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "assumed", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc_arr", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "daa", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "auto_arr", pinned
+! CHECK: %[[PAR_S_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFtarget_parallelEs"}
+! CHECK: %[[PAR_S_DECL:.*]]:2 = hlfir.declare %[[PAR_S_ALLOCA]]
+! CHECK: %[[PAR_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_parallelEarr"}
+! CHECK: %[[PAR_ARR_DECL:.*]]:2 = hlfir.declare %[[PAR_ARR_ALLOCA]]
+! CHECK: %[[PAR_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFtarget_parallelEptr"}
+! CHECK: %[[PAR_PTR_DECL:.*]]:2 = hlfir.declare %[[PAR_PTR_ALLOCA]]
+! CHECK: %[[PAR_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFtarget_parallelEd"}
+! CHECK: %[[PAR_D_DECL:.*]]:2 = hlfir.declare %[[PAR_D_ALLOCA]]
+! CHECK: %[[PAR_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_parallelEptr_arr"}
+! CHECK: %[[PAR_PTR_ARR_DECL:.*]]:2 = hlfir.declare %[[PAR_PTR_ARR_ALLOCA]]
+! CHECK: fir.store %[[PAR_ASSUMED_DECL]]#0 to %[[PAR_ASSUMED_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
+! CHECK: fir.store %[[PAR_AUTO_ARR_DECL]]#0 to %[[PAR_AUTO_ARR_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
+! CHECK: omp.parallel private(
+! CHECK-SAME: @_QFtarget_parallelEs_private_i32 %[[PAR_S_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallelEarr_private_10xi32 %[[PAR_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallelEalloc_private_box_heap_i32 %[[PAR_ALLOC_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallelEptr_private_box_ptr_i32 %[[PAR_PTR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallelEd_private_rec__QMtypesTdt %[[PAR_D_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallelEda_private_rec__QMtypesTdt_alloc %[[PAR_DA_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallelEassumed_private_box_Uxi32 %[[PAR_ASSUMED_COPY]] -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallelEalloc_arr_private_box_heap_Uxi32 %[[PAR_ALLOC_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallelEptr_arr_private_box_ptr_Uxi32 %[[PAR_PTR_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallelEdaa_private_rec__QMtypesTdt_alloc_arr %[[PAR_DAA_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallelEauto_arr_private_box_Uxi32 %[[PAR_AUTO_ARR_COPY]] -> %arg{{[0-9]+}} : !fir.ref<i32>, !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.type<_QMtypesTdt{a:i32,b:f32}>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>) {
+
+subroutine target_teams_distribute(n, assumed)
+  use types
+  integer :: n, i, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target teams distribute private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+  do i = 1, n
+    s = i
+  end do
+  !$omp end target teams distribute
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_teams_distribute
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: %[[TTD_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTD_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TTD_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
+! CHECK: %[[TTD_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
+! CHECK: %[[TTD_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
+! CHECK: %[[TTD_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTD_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[TTD_ASSUMED_MEMBER]] {{.*}}) name("assumed")
+! CHECK: %[[TTD_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
+! CHECK: %[[TTD_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTD_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TTD_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
+! CHECK: %[[TTD_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
+! CHECK: %[[TTD_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
+! CHECK: %[[TTD_AUTO_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("auto_arr")
+! CHECK: %[[TTD_I_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("i")
+! CHECK: %[[TTD_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
+! CHECK: %[[TTD_BOUND_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("")
+! CHECK: omp.target kernel_type(generic) host_eval({{.*}}) map_entries(%[[TTD_ALLOC_MAP]] -> %{{.*}}, %[[TTD_DA_MAP]] -> %{{.*}}, %[[TTD_ASSUMED_MAP]] -> %{{.*}}, %[[TTD_ALLOC_ARR_MAP]] -> %{{.*}}, %[[TTD_DAA_MAP]] -> %{{.*}}, %[[TTD_AUTO_ARR_MAP]] -> %{{.*}}, %[[TTD_I_MAP]] -> %{{.*}}, %[[TTD_N_MAP]] -> %{{.*}}, %[[TTD_BOUND_N_MAP]] -> %{{.*}}, %[[TTD_ALLOC_ATTACH]] -> %{{.*}}, %[[TTD_ASSUMED_ATTACH]] -> %{{.*}}, %[[TTD_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[TTD_ALLOC_MEMBER]] -> %{{.*}}, %[[TTD_ASSUMED_MEMBER]] -> %{{.*}}, %[[TTD_ALLOC_ARR_MEMBER]] -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) {
+! CHECK: %[[TTD_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teams_distributeEalloc"}
+! CHECK: %[[TTD_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distributeEda"}
+! CHECK: %[[TTD_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distributeEassumed"}
+! CHECK: %[[TTD_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teams_distributeEalloc_arr"}
+! CHECK: %[[TTD_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distributeEdaa"}
+! CHECK: %[[TTD_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) {uniq_name = "_QFtarget_teams_distributeEauto_arr"}
+! CHECK: %[[TTD_I_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distributeEi"}
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "da", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "assumed", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc_arr", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "daa", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "auto_arr", pinned
+! CHECK: %[[TTD_S_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFtarget_teams_distributeEs"}
+! CHECK: %[[TTD_S_DECL:.*]]:2 = hlfir.declare %[[TTD_S_ALLOCA]]
+! CHECK: %[[TTD_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_teams_distributeEarr"}
+! CHECK: %[[TTD_ARR_DECL:.*]]:2 = hlfir.declare %[[TTD_ARR_ALLOCA]]
+! CHECK: %[[TTD_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFtarget_teams_distributeEptr"}
+! CHECK: %[[TTD_PTR_DECL:.*]]:2 = hlfir.declare %[[TTD_PTR_ALLOCA]]
+! CHECK: %[[TTD_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFtarget_teams_distributeEd"}
+! CHECK: %[[TTD_D_DECL:.*]]:2 = hlfir.declare %[[TTD_D_ALLOCA]]
+! CHECK: %[[TTD_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_teams_distributeEptr_arr"}
+! CHECK: %[[TTD_PTR_ARR_DECL:.*]]:2 = hlfir.declare %[[TTD_PTR_ARR_ALLOCA]]
+! CHECK: omp.teams {
+! CHECK: fir.store %[[TTD_ASSUMED_DECL]]#0 to %[[TTD_ASSUMED_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
+! CHECK: fir.store %[[TTD_AUTO_ARR_DECL]]#0 to %[[TTD_AUTO_ARR_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
+! CHECK: omp.distribute private(
+! CHECK-SAME: @_QFtarget_teams_distributeEs_private_i32 %[[TTD_S_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distributeEarr_private_10xi32 %[[TTD_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distributeEalloc_private_box_heap_i32 %[[TTD_ALLOC_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distributeEptr_private_box_ptr_i32 %[[TTD_PTR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distributeEd_private_rec__QMtypesTdt %[[TTD_D_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distributeEda_private_rec__QMtypesTdt_alloc %[[TTD_DA_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distributeEassumed_private_box_Uxi32 %[[TTD_ASSUMED_COPY]] -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distributeEalloc_arr_private_box_heap_Uxi32 %[[TTD_ALLOC_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distributeEptr_arr_private_box_ptr_Uxi32 %[[TTD_PTR_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distributeEdaa_private_rec__QMtypesTdt_alloc_arr %[[TTD_DAA_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distributeEauto_arr_private_box_Uxi32 %[[TTD_AUTO_ARR_COPY]] -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distributeEi_private_i32 %[[TTD_I_DECL]]#0 -> %arg{{[0-9]+}} : !fir.ref<i32>, !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.type<_QMtypesTdt{a:i32,b:f32}>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<i32>) {
+
+subroutine target_only(n, assumed)
+  use types
+  integer :: n, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+  s = 1
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_only
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: %[[ONLY_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) capture(ByRef) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>, i32) name("")
+! CHECK: %[[ONLY_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, to) {{.*}} members(%[[ONLY_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>)
+! CHECK: %[[ONLY_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>, i32)
+! CHECK: %[[ONLY_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(tofrom) capture(ByRef) mapper(@_QMtypesTdt_alloc_omp_default_mapper)
+! CHECK: %[[ONLY_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("")
+! CHECK: %[[ONLY_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, to) {{.*}} members(%[[ONLY_ASSUMED_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>)
+! CHECK: %[[ONLY_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, i32)
+! CHECK: %[[ONLY_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("")
+! CHECK: %[[ONLY_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, to) {{.*}} members(%[[ONLY_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>)
+! CHECK: %[[ONLY_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, i32)
+! CHECK: %[[ONLY_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(tofrom) capture(ByRef) mapper(@_QMtypesTdt_alloc_arr_omp_default_mapper)
+! CHECK: %[[ONLY_AUTO_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("")
+! CHECK: %[[ONLY_AUTO_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, to) {{.*}} members(%[[ONLY_AUTO_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>)
+! CHECK: %[[ONLY_AUTO_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, i32)
+! CHECK: omp.target kernel_type(generic) map_entries(%[[ONLY_ALLOC_MAP]] -> %{{.*}}, %[[ONLY_DA_MAP]] -> %{{.*}}, %[[ONLY_ASSUMED_MAP]] -> %{{.*}}, %[[ONLY_ALLOC_ARR_MAP]] -> %{{.*}}, %[[ONLY_DAA_MAP]] -> %{{.*}}, %[[ONLY_AUTO_ARR_MAP]] -> %{{.*}}, %[[ONLY_ALLOC_ATTACH]] -> %{{.*}}, %[[ONLY_ASSUMED_ATTACH]] -> %{{.*}}, %[[ONLY_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[ONLY_AUTO_ARR_ATTACH]] -> %{{.*}}, %[[ONLY_ALLOC_MEMBER]] -> %{{.*}}, %[[ONLY_ASSUMED_MEMBER]] -> %{{.*}}, %[[ONLY_ALLOC_ARR_MEMBER]] -> %{{.*}}, %[[ONLY_AUTO_ARR_MEMBER]] -> %{{.*}} : {{.*}}) private(
+! CHECK-SAME: @_QFtarget_onlyEs_private_i32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_onlyEarr_private_10xi32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_onlyEalloc_private_box_heap_i32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}} [map_idx=0],
+! CHECK-SAME: @_QFtarget_onlyEptr_private_box_ptr_i32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_onlyEd_private_rec__QMtypesTdt %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_onlyEda_private_rec__QMtypesTdt_alloc %{{[0-9]+}}#0 -> %arg{{[0-9]+}} [map_idx=1],
+! CHECK-SAME: @_QFtarget_onlyEassumed_private_box_Uxi32 %{{[0-9]+}} -> %arg{{[0-9]+}} [map_idx=2],
+! CHECK-SAME: @_QFtarget_onlyEalloc_arr_private_box_heap_Uxi32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}} [map_idx=3],
+! CHECK-SAME: @_QFtarget_onlyEptr_arr_private_box_ptr_Uxi32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_onlyEdaa_private_rec__QMtypesTdt_alloc_arr %{{[0-9]+}}#0 -> %arg{{[0-9]+}} [map_idx=4],
+! CHECK-SAME: @_QFtarget_onlyEauto_arr_private_box_Uxi32 %{{[0-9]+}} -> %arg{{[0-9]+}} [map_idx=5] : !fir.ref<i32>, !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.type<_QMtypesTdt{a:i32,b:f32}>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>) {
+
+subroutine target_nested(n, assumed)
+  use types
+  integer :: n, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target
+  !$omp parallel private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+  s = 1
+  !$omp end parallel
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_nested
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: %[[NEST_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[NEST_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[NEST_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
+! CHECK: %[[NEST_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
+! CHECK: %[[NEST_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
+! CHECK: %[[NEST_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[NEST_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[NEST_ASSUMED_MEMBER]] {{.*}}) name("assumed")
+! CHECK: %[[NEST_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
+! CHECK: %[[NEST_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[NEST_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[NEST_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
+! CHECK: %[[NEST_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
+! CHECK: %[[NEST_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
+! CHECK: %[[NEST_AUTO_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("auto_arr")
+! CHECK: %[[NEST_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("")
+! CHECK: omp.target kernel_type(generic) map_entries(%[[NEST_ALLOC_MAP]] -> %{{.*}}, %[[NEST_DA_MAP]] -> %{{.*}}, %[[NEST_ASSUMED_MAP]] -> %{{.*}}, %[[NEST_ALLOC_ARR_MAP]] -> %{{.*}}, %[[NEST_DAA_MAP]] -> %{{.*}}, %[[NEST_AUTO_ARR_MAP]] -> %{{.*}}, %[[NEST_N_MAP]] -> %{{.*}}, %[[NEST_ALLOC_ATTACH]] -> %{{.*}}, %[[NEST_ASSUMED_ATTACH]] -> %{{.*}}, %[[NEST_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[NEST_ALLOC_MEMBER]] -> %{{.*}}, %[[NEST_ASSUMED_MEMBER]] -> %{{.*}}, %[[NEST_ALLOC_ARR_MEMBER]] -> %{{.*}} : {{.*}}) {
+! CHECK: omp.parallel private(
+! CHECK-SAME: @_QFtarget_nestedEs_private_i32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_nestedEarr_private_10xi32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_nestedEalloc_private_box_heap_i32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_nestedEptr_private_box_ptr_i32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_nestedEd_private_rec__QMtypesTdt %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_nestedEda_private_rec__QMtypesTdt_alloc %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_nestedEassumed_private_box_Uxi32 %{{[0-9]+}} -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_nestedEalloc_arr_private_box_heap_Uxi32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_nestedEptr_arr_private_box_ptr_Uxi32 %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_nestedEdaa_private_rec__QMtypesTdt_alloc_arr %{{[0-9]+}}#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_nestedEauto_arr_private_box_Uxi32 %{{[0-9]+}} -> %arg{{[0-9]+}} : !fir.ref<i32>, !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.type<_QMtypesTdt{a:i32,b:f32}>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>) {
+
+subroutine target_teams_distribute_simd(n, assumed)
+  use types
+  integer :: n, i, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target teams distribute simd private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+  do i = 1, n
+    s = i
+  end do
+  !$omp end target teams distribute simd
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_teams_distribute_simd
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: %[[TTDS_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTDS_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TTDS_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
+! CHECK: %[[TTDS_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
+! CHECK: %[[TTDS_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
+! CHECK: %[[TTDS_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTDS_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[TTDS_ASSUMED_MEMBER]] {{.*}}) name("assumed")
+! CHECK: %[[TTDS_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
+! CHECK: %[[TTDS_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTDS_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TTDS_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
+! CHECK: %[[TTDS_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
+! CHECK: %[[TTDS_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
+! CHECK: %[[TTDS_AUTO_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("auto_arr")
+! CHECK: %[[TTDS_I_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("i")
+! CHECK: %[[TTDS_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
+! CHECK: %[[TTDS_BOUND_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("")
+! CHECK: omp.target kernel_type(generic) host_eval({{.*}}) map_entries(%[[TTDS_ALLOC_MAP]] -> %{{.*}}, %[[TTDS_DA_MAP]] -> %{{.*}}, %[[TTDS_ASSUMED_MAP]] -> %{{.*}}, %[[TTDS_ALLOC_ARR_MAP]] -> %{{.*}}, %[[TTDS_DAA_MAP]] -> %{{.*}}, %[[TTDS_AUTO_ARR_MAP]] -> %{{.*}}, %[[TTDS_I_MAP]] -> %{{.*}}, %[[TTDS_N_MAP]] -> %{{.*}}, %[[TTDS_BOUND_N_MAP]] -> %{{.*}}, %[[TTDS_ALLOC_ATTACH]] -> %{{.*}}, %[[TTDS_ASSUMED_ATTACH]] -> %{{.*}}, %[[TTDS_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[TTDS_ALLOC_MEMBER]] -> %{{.*}}, %[[TTDS_ASSUMED_MEMBER]] -> %{{.*}}, %[[TTDS_ALLOC_ARR_MEMBER]] -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) {
+! CHECK: %[[TTDS_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teams_distribute_simdEalloc"}
+! CHECK: %[[TTDS_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distribute_simdEda"}
+! CHECK: %[[TTDS_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distribute_simdEassumed"}
+! CHECK: %[[TTDS_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teams_distribute_simdEalloc_arr"}
+! CHECK: %[[TTDS_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distribute_simdEdaa"}
+! CHECK: %[[TTDS_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) {uniq_name = "_QFtarget_teams_distribute_simdEauto_arr"}
+! CHECK: %[[TTDS_I_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distribute_simdEi"}
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "da", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "assumed", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc_arr", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "daa", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "auto_arr", pinned
+! CHECK: %[[TTDS_S_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFtarget_teams_distribute_simdEs"}
+! CHECK: %[[TTDS_S_DECL:.*]]:2 = hlfir.declare %[[TTDS_S_ALLOCA]]
+! CHECK: %[[TTDS_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_teams_distribute_simdEarr"}
+! CHECK: %[[TTDS_ARR_DECL:.*]]:2 = hlfir.declare %[[TTDS_ARR_ALLOCA]]
+! CHECK: %[[TTDS_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFtarget_teams_distribute_simdEptr"}
+! CHECK: %[[TTDS_PTR_DECL:.*]]:2 = hlfir.declare %[[TTDS_PTR_ALLOCA]]
+! CHECK: %[[TTDS_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFtarget_teams_distribute_simdEd"}
+! CHECK: %[[TTDS_D_DECL:.*]]:2 = hlfir.declare %[[TTDS_D_ALLOCA]]
+! CHECK: %[[TTDS_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_teams_distribute_simdEptr_arr"}
+! CHECK: %[[TTDS_PTR_ARR_DECL:.*]]:2 = hlfir.declare %[[TTDS_PTR_ARR_ALLOCA]]
+! CHECK: omp.teams {
+! CHECK: fir.store %[[TTDS_ASSUMED_DECL]]#0 to %[[TTDS_ASSUMED_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
+! CHECK: fir.store %[[TTDS_AUTO_ARR_DECL]]#0 to %[[TTDS_AUTO_ARR_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
+! CHECK: omp.distribute {
+! CHECK: omp.simd private(
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEs_private_i32 %[[TTDS_S_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEarr_private_10xi32 %[[TTDS_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEalloc_private_box_heap_i32 %[[TTDS_ALLOC_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEptr_private_box_ptr_i32 %[[TTDS_PTR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEd_private_rec__QMtypesTdt %[[TTDS_D_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEda_private_rec__QMtypesTdt_alloc %[[TTDS_DA_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEassumed_private_box_Uxi32 %[[TTDS_ASSUMED_COPY]] -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEalloc_arr_private_box_heap_Uxi32 %[[TTDS_ALLOC_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEptr_arr_private_box_ptr_Uxi32 %[[TTDS_PTR_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEdaa_private_rec__QMtypesTdt_alloc_arr %[[TTDS_DAA_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEauto_arr_private_box_Uxi32 %[[TTDS_AUTO_ARR_COPY]] -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_teams_distribute_simdEi_private_i32 %[[TTDS_I_DECL]]#0 -> %arg{{[0-9]+}} : !fir.ref<i32>, !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.type<_QMtypesTdt{a:i32,b:f32}>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<i32>) {
+
+subroutine target_parallel_do(n, assumed)
+  use types
+  integer :: n, i, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target parallel do private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+  do i = 1, n
+    s = i
+  end do
+  !$omp end target parallel do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_parallel_do
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: %[[PDO_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PDO_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[PDO_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
+! CHECK: %[[PDO_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
+! CHECK: %[[PDO_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
+! CHECK: %[[PDO_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PDO_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[PDO_ASSUMED_MEMBER]] {{.*}}) name("assumed")
+! CHECK: %[[PDO_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
+! CHECK: %[[PDO_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PDO_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[PDO_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
+! CHECK: %[[PDO_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
+! CHECK: %[[PDO_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
+! CHECK: %[[PDO_AUTO_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("auto_arr")
+! CHECK: %[[PDO_I_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("i")
+! CHECK: %[[PDO_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
+! CHECK: %[[PDO_BOUND_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("")
+! CHECK: omp.target kernel_type(spmd) host_eval({{.*}}) map_entries(%[[PDO_ALLOC_MAP]] -> %{{.*}}, %[[PDO_DA_MAP]] -> %{{.*}}, %[[PDO_ASSUMED_MAP]] -> %{{.*}}, %[[PDO_ALLOC_ARR_MAP]] -> %{{.*}}, %[[PDO_DAA_MAP]] -> %{{.*}}, %[[PDO_AUTO_ARR_MAP]] -> %{{.*}}, %[[PDO_I_MAP]] -> %{{.*}}, %[[PDO_N_MAP]] -> %{{.*}}, %[[PDO_BOUND_N_MAP]] -> %{{.*}}, %[[PDO_ALLOC_ATTACH]] -> %{{.*}}, %[[PDO_ASSUMED_ATTACH]] -> %{{.*}}, %[[PDO_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[PDO_ALLOC_MEMBER]] -> %{{.*}}, %[[PDO_ASSUMED_MEMBER]] -> %{{.*}}, %[[PDO_ALLOC_ARR_MEMBER]] -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) {
+! CHECK: %[[PDO_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_parallel_doEalloc"}
+! CHECK: %[[PDO_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallel_doEda"}
+! CHECK: %[[PDO_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallel_doEassumed"}
+! CHECK: %[[PDO_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_parallel_doEalloc_arr"}
+! CHECK: %[[PDO_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallel_doEdaa"}
+! CHECK: %[[PDO_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) {uniq_name = "_QFtarget_parallel_doEauto_arr"}
+! CHECK: %[[PDO_I_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallel_doEi"}
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "da", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "assumed", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc_arr", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "daa", pinned
+! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "auto_arr", pinned
+! CHECK: %[[PDO_S_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFtarget_parallel_doEs"}
+! CHECK: %[[PDO_S_DECL:.*]]:2 = hlfir.declare %[[PDO_S_ALLOCA]]
+! CHECK: %[[PDO_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_parallel_doEarr"}
+! CHECK: %[[PDO_ARR_DECL:.*]]:2 = hlfir.declare %[[PDO_ARR_ALLOCA]]
+! CHECK: %[[PDO_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFtarget_parallel_doEptr"}
+! CHECK: %[[PDO_PTR_DECL:.*]]:2 = hlfir.declare %[[PDO_PTR_ALLOCA]]
+! CHECK: %[[PDO_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFtarget_parallel_doEd"}
+! CHECK: %[[PDO_D_DECL:.*]]:2 = hlfir.declare %[[PDO_D_ALLOCA]]
+! CHECK: %[[PDO_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_parallel_doEptr_arr"}
+! CHECK: %[[PDO_PTR_ARR_DECL:.*]]:2 = hlfir.declare %[[PDO_PTR_ARR_ALLOCA]]
+! CHECK: omp.parallel {
+! CHECK: fir.store %[[PDO_ASSUMED_DECL]]#0 to %[[PDO_ASSUMED_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
+! CHECK: fir.store %[[PDO_AUTO_ARR_DECL]]#0 to %[[PDO_AUTO_ARR_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
+! CHECK: omp.wsloop private(
+! CHECK-SAME: @_QFtarget_parallel_doEs_private_i32 %[[PDO_S_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallel_doEarr_private_10xi32 %[[PDO_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallel_doEalloc_private_box_heap_i32 %[[PDO_ALLOC_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallel_doEptr_private_box_ptr_i32 %[[PDO_PTR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallel_doEd_private_rec__QMtypesTdt %[[PDO_D_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallel_doEda_private_rec__QMtypesTdt_alloc %[[PDO_DA_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallel_doEassumed_private_box_Uxi32 %[[PDO_ASSUMED_COPY]] -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallel_doEalloc_arr_private_box_heap_Uxi32 %[[PDO_ALLOC_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallel_doEptr_arr_private_box_ptr_Uxi32 %[[PDO_PTR_ARR_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallel_doEdaa_private_rec__QMtypesTdt_alloc_arr %[[PDO_DAA_DECL]]#0 -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallel_doEauto_arr_private_box_Uxi32 %[[PDO_AUTO_ARR_COPY]] -> %arg{{[0-9]+}},
+! CHECK-SAME: @_QFtarget_parallel_doEi_private_i32 %[[PDO_I_DECL]]#0 -> %arg{{[0-9]+}} : !fir.ref<i32>, !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.type<_QMtypesTdt{a:i32,b:f32}>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<i32>) {
diff --git a/flang/test/Lower/OpenMP/target-nested-private-unified.f90 b/flang/test/Lower/OpenMP/target-nested-private-unified.f90
new file mode 100644
index 00000000000000..0ce63fba5c4401
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-nested-private-unified.f90
@@ -0,0 +1,304 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+module nested_private_types
+  type :: dt
+    integer :: a
+    real :: b
+  end type
+  type :: dt_alloc
+    integer, allocatable :: a
+  end type
+  type :: dt_alloc_arr
+    integer, allocatable :: a(:)
+  end type
+end module
+
+subroutine nested_target_teams(n, assumed)
+  use nested_private_types
+  integer :: n, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target
+    !$omp teams private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+      s = 1
+    !$omp end teams
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPnested_target_teams
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: omp.map.info {{.*}} name("alloc")
+! CHECK: omp.map.info {{.*}} name("da")
+! CHECK: omp.map.info {{.*}} name("assumed")
+! CHECK: omp.map.info {{.*}} name("alloc_arr")
+! CHECK: omp.map.info {{.*}} name("daa")
+! CHECK: omp.map.info {{.*}} name("auto_arr")
+! CHECK: omp.target
+! CHECK: omp.teams
+! CHECK: fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFnested_target_teamsEs"}
+! CHECK: fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFnested_target_teamsEarr"}
+! CHECK: fir.alloca !fir.box<!fir.heap<i32>> {bindc_name = "alloc", pinned, uniq_name = "_QFnested_target_teamsEalloc"}
+! CHECK: fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFnested_target_teamsEptr"}
+! CHECK: fir.alloca !fir.type<_QMnested_private_typesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFnested_target_teamsEd"}
+! CHECK: fir.alloca !fir.type<_QMnested_private_typesTdt_alloc{a:!fir.box<!fir.heap<i32>>}> {bindc_name = "da", pinned, uniq_name = "_QFnested_target_teamsEda"}
+! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} {bindc_name = "assumed", pinned, uniq_name = "_QFnested_target_teamsEassumed"}
+! CHECK: fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = "alloc_arr", pinned, uniq_name = "_QFnested_target_teamsEalloc_arr"}
+! CHECK: fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFnested_target_teamsEptr_arr"}
+! CHECK: fir.alloca !fir.type<_QMnested_private_typesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}> {bindc_name = "daa", pinned, uniq_name = "_QFnested_target_teamsEdaa"}
+! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} {bindc_name = "auto_arr", pinned, uniq_name = "_QFnested_target_teamsEauto_arr"}
+
+subroutine nested_target_parallel(n, assumed)
+  use nested_private_types
+  integer :: n, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target
+    !$omp parallel private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+      s = 1
+    !$omp end parallel
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPnested_target_parallel
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: omp.map.info {{.*}} name("alloc")
+! CHECK: omp.map.info {{.*}} name("da")
+! CHECK: omp.map.info {{.*}} name("assumed")
+! CHECK: omp.map.info {{.*}} name("alloc_arr")
+! CHECK: omp.map.info {{.*}} name("daa")
+! CHECK: omp.map.info {{.*}} name("auto_arr")
+! CHECK: omp.target
+! CHECK: omp.parallel private(
+! CHECK-SAME: @_QFnested_target_parallelEs_private_i32
+! CHECK-SAME: @_QFnested_target_parallelEarr_private_10xi32
+! CHECK-SAME: @_QFnested_target_parallelEalloc_private_box_heap_i32
+! CHECK-SAME: @_QFnested_target_parallelEptr_private_box_ptr_i32
+! CHECK-SAME: @_QFnested_target_parallelEd_private_rec__QMnested_private_typesTdt
+! CHECK-SAME: @_QFnested_target_parallelEda_private_rec__QMnested_private_typesTdt_alloc
+! CHECK-SAME: @_QFnested_target_parallelEassumed_private_box_Uxi32
+! CHECK-SAME: @_QFnested_target_parallelEalloc_arr_private_box_heap_Uxi32
+! CHECK-SAME: @_QFnested_target_parallelEptr_arr_private_box_ptr_Uxi32
+! CHECK-SAME: @_QFnested_target_parallelEdaa_private_rec__QMnested_private_typesTdt_alloc_arr
+! CHECK-SAME: @_QFnested_target_parallelEauto_arr_private_box_Uxi32
+
+subroutine nested_target_teams_distribute(n, assumed)
+  use nested_private_types
+  integer :: n, i, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target
+    !$omp teams distribute private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+    do i = 1, n
+      s = i
+    end do
+    !$omp end teams distribute
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPnested_target_teams_distribute
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: omp.map.info {{.*}} name("alloc")
+! CHECK: omp.map.info {{.*}} name("da")
+! CHECK: omp.map.info {{.*}} name("assumed")
+! CHECK: omp.map.info {{.*}} name("alloc_arr")
+! CHECK: omp.map.info {{.*}} name("daa")
+! CHECK: omp.map.info {{.*}} name("auto_arr")
+! CHECK: omp.target
+! CHECK: omp.teams
+! CHECK: omp.distribute private(
+! CHECK-SAME: @_QFnested_target_teams_distributeEs_private_i32
+! CHECK-SAME: @_QFnested_target_teams_distributeEarr_private_10xi32
+! CHECK-SAME: @_QFnested_target_teams_distributeEalloc_private_box_heap_i32
+! CHECK-SAME: @_QFnested_target_teams_distributeEptr_private_box_ptr_i32
+! CHECK-SAME: @_QFnested_target_teams_distributeEd_private_rec__QMnested_private_typesTdt
+! CHECK-SAME: @_QFnested_target_teams_distributeEda_private_rec__QMnested_private_typesTdt_alloc
+! CHECK-SAME: @_QFnested_target_teams_distributeEassumed_private_box_Uxi32
+! CHECK-SAME: @_QFnested_target_teams_distributeEalloc_arr_private_box_heap_Uxi32
+! CHECK-SAME: @_QFnested_target_teams_distributeEptr_arr_private_box_ptr_Uxi32
+! CHECK-SAME: @_QFnested_target_teams_distributeEdaa_private_rec__QMnested_private_typesTdt_alloc_arr
+! CHECK-SAME: @_QFnested_target_teams_distributeEauto_arr_private_box_Uxi32
+
+subroutine nested_target_teams_distribute_simd(n, assumed)
+  use nested_private_types
+  integer :: n, i, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target
+    !$omp teams distribute simd private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+    do i = 1, n
+      s = i
+    end do
+    !$omp end teams distribute simd
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPnested_target_teams_distribute_simd
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: omp.map.info {{.*}} name("alloc")
+! CHECK: omp.map.info {{.*}} name("da")
+! CHECK: omp.map.info {{.*}} name("assumed")
+! CHECK: omp.map.info {{.*}} name("alloc_arr")
+! CHECK: omp.map.info {{.*}} name("daa")
+! CHECK: omp.map.info {{.*}} name("auto_arr")
+! CHECK: omp.target
+! CHECK: omp.teams
+! CHECK: omp.distribute
+! CHECK: omp.simd private(
+! CHECK-SAME: @_QFnested_target_teams_distribute_simdEs_private_i32
+! CHECK-SAME: @_QFnested_target_teams_distribute_simdEarr_private_10xi32
+! CHECK-SAME: @_QFnested_target_teams_distribute_simdEalloc_private_box_heap_i32
+! CHECK-SAME: @_QFnested_target_teams_distribute_simdEptr_private_box_ptr_i32
+! CHECK-SAME: @_QFnested_target_teams_distribute_simdEd_private_rec__QMnested_private_typesTdt
+! CHECK-SAME: @_QFnested_target_teams_distribute_simdEda_private_rec__QMnested_private_typesTdt_alloc
+! CHECK-SAME: @_QFnested_target_teams_distribute_simdEassumed_private_box_Uxi32
+! CHECK-SAME: @_QFnested_target_teams_distribute_simdEalloc_arr_private_box_heap_Uxi32
+! CHECK-SAME: @_QFnested_target_teams_distribute_simdEptr_arr_private_box_ptr_Uxi32
+! CHECK-SAME: @_QFnested_target_teams_distribute_simdEdaa_private_rec__QMnested_private_typesTdt_alloc_arr
+! CHECK-SAME: @_QFnested_target_teams_distribute_simdEauto_arr_private_box_Uxi32
+
+subroutine nested_target_parallel_do(n, assumed)
+  use nested_private_types
+  integer :: n, i, s, arr(10), assumed(:)
+  integer, allocatable :: alloc, alloc_arr(:)
+  integer, pointer :: ptr, ptr_arr(:)
+  type(dt) :: d
+  type(dt_alloc) :: da
+  type(dt_alloc_arr) :: daa
+  integer :: auto_arr(n)
+  !$omp target
+    !$omp parallel do private(s, arr, alloc, ptr, d, da, assumed, alloc_arr, ptr_arr, daa, auto_arr)
+    do i = 1, n
+      s = i
+    end do
+    !$omp end parallel do
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPnested_target_parallel_do
+! CHECK-NOT: omp.map.info {{.*}} name("s")
+! CHECK-NOT: omp.map.info {{.*}} name("arr")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr")
+! CHECK-NOT: omp.map.info {{.*}} name("d")
+! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
+! CHECK: omp.map.info {{.*}} name("alloc")
+! CHECK: omp.map.info {{.*}} name("da")
+! CHECK: omp.map.info {{.*}} name("assumed")
+! CHECK: omp.map.info {{.*}} name("alloc_arr")
+! CHECK: omp.map.info {{.*}} name("daa")
+! CHECK: omp.map.info {{.*}} name("auto_arr")
+! CHECK: omp.target
+! CHECK: omp.parallel
+! CHECK: omp.wsloop private(
+! CHECK-SAME: @_QFnested_target_parallel_doEs_private_i32
+! CHECK-SAME: @_QFnested_target_parallel_doEarr_private_10xi32
+! CHECK-SAME: @_QFnested_target_parallel_doEalloc_private_box_heap_i32
+! CHECK-SAME: @_QFnested_target_parallel_doEptr_private_box_ptr_i32
+! CHECK-SAME: @_QFnested_target_parallel_doEd_private_rec__QMnested_private_typesTdt
+! CHECK-SAME: @_QFnested_target_parallel_doEda_private_rec__QMnested_private_typesTdt_alloc
+! CHECK-SAME: @_QFnested_target_parallel_doEassumed_private_box_Uxi32
+! CHECK-SAME: @_QFnested_target_parallel_doEalloc_arr_private_box_heap_Uxi32
+! CHECK-SAME: @_QFnested_target_parallel_doEptr_arr_private_box_ptr_Uxi32
+! CHECK-SAME: @_QFnested_target_parallel_doEdaa_private_rec__QMnested_private_typesTdt_alloc_arr
+! CHECK-SAME: @_QFnested_target_parallel_doEauto_arr_private_box_Uxi32
+
+subroutine nested_target_parallel_intervening_code()
+  integer :: guard, k
+  !$omp target
+    guard = 0
+    !$omp parallel private(k)
+      k = 10
+    !$omp end parallel
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPnested_target_parallel_intervening_code
+! CHECK: omp.map.info {{.*}} name("k")
+! CHECK: omp.target
+! CHECK: omp.parallel private({{.*}}@_QFnested_target_parallel_intervening_codeEk_private_i32
+
+subroutine nested_target_parallel_do_intervening_code()
+  integer :: guard, i, k
+  !$omp target
+    guard = 0
+    !$omp parallel do private(k)
+    do i = 1, 10
+      k = i
+    end do
+    !$omp end parallel do
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPnested_target_parallel_do_intervening_code
+! CHECK: omp.map.info {{.*}} name("k")
+! CHECK: omp.target
+! CHECK: omp.parallel
+! CHECK: omp.wsloop private({{.*}}@_QFnested_target_parallel_do_intervening_codeEk_private_i32
+
+subroutine nested_target_parallel_both_private()
+  integer :: k
+  !$omp target private(k)
+    !$omp parallel private(k)
+      k = 10
+    !$omp end parallel
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPnested_target_parallel_both_private
+! CHECK-NOT: omp.map.info {{.*}} name("k")
+! CHECK: omp.target kernel_type(generic) private(@_QFnested_target_parallel_both_privateEk_private_i32 %{{.*}}#0 -> %[[TP_K_ARG:arg[0-9]+]] : !fir.ref<i32>) {
+! CHECK: %[[TP_K_DECL:.*]]:2 = hlfir.declare %[[TP_K_ARG]] {uniq_name = "_QFnested_target_parallel_both_privateEk"}
+! CHECK: omp.parallel private(@_QFnested_target_parallel_both_privateEk_private_i32 %[[TP_K_DECL]]#0 -> %[[PAR_K_ARG:arg[0-9]+]] : !fir.ref<i32>) {
+! CHECK: hlfir.declare %[[PAR_K_ARG]] {uniq_name = "_QFnested_target_parallel_both_privateEk"}
+
+subroutine nested_target_teams_distribute_both_private()
+  integer :: i, k
+  !$omp target private(k)
+    !$omp teams distribute private(k)
+    do i = 1, 10
+      k = i
+    end do
+    !$omp end teams distribute
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPnested_target_teams_distribute_both_private
+! CHECK-NOT: omp.map.info {{.*}} name("k")
+! CHECK: omp.map.info {{.*}} name("i")
+! CHECK-NOT: omp.map.info {{.*}} name("k")
+! CHECK: omp.target {{.*}}private(@_QFnested_target_teams_distribute_both_privateEk_private_i32 %{{.*}}#0 -> %[[TTD_K_ARG:arg[0-9]+]]
+! CHECK: %[[TTD_K_DECL:.*]]:2 = hlfir.declare %[[TTD_K_ARG]] {uniq_name = "_QFnested_target_teams_distribute_both_privateEk"}
+! CHECK: omp.teams
+! CHECK: omp.distribute private({{.*}}@_QFnested_target_teams_distribute_both_privateEk_private_i32 %[[TTD_K_DECL]]#0 -> %[[DIST_K_ARG:arg[0-9]+]]
+! CHECK: hlfir.declare %[[DIST_K_ARG]] {uniq_name = "_QFnested_target_teams_distribute_both_privateEk"}
diff --git a/flang/test/Lower/OpenMP/target-nested-private.f90 b/flang/test/Lower/OpenMP/target-nested-private.f90
new file mode 100644
index 00000000000000..a32cc72af118d5
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-nested-private.f90
@@ -0,0 +1,67 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+subroutine target_nested_teams_distribute_private()
+  integer :: i, k
+  !$omp target
+    !$omp teams distribute private(k)
+    do i = 1, 10
+      k = 10
+    end do
+    !$omp end teams distribute
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_nested_teams_distribute_private
+! CHECK-NOT: omp.map.info {{.*}} name("k")
+! CHECK: omp.map.info {{.*}} name("i")
+! CHECK-NOT: omp.map.info {{.*}} name("k")
+! CHECK: omp.target
+! CHECK: fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFtarget_nested_teams_distribute_privateEk"}
+! CHECK: omp.teams
+! CHECK: omp.distribute private({{.*}}@_QFtarget_nested_teams_distribute_privateEk_private_i32
+
+subroutine target_nested_teams_distribute_private_thread_limit(k)
+  integer :: i, k
+  !$omp target
+    !$omp teams distribute private(k) thread_limit(k)
+    do i = 1, 10
+      k = 10
+    end do
+    !$omp end teams distribute
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_nested_teams_distribute_private_thread_limit
+! CHECK: omp.map.info {{.*}} name("k")
+! CHECK: omp.target
+! CHECK: omp.teams thread_limit
+! CHECK: omp.distribute private({{.*}}@_QFtarget_nested_teams_distribute_private_thread_limitEk_private_i32
+
+subroutine target_nested_parallel_private()
+  integer :: k
+  !$omp target
+    !$omp parallel private(k)
+      k = 10
+    !$omp end parallel
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_nested_parallel_private
+! CHECK-NOT: omp.map.info {{.*}} name("k")
+! CHECK: omp.target
+! CHECK: fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFtarget_nested_parallel_privateEk"}
+! CHECK: omp.parallel private({{.*}}@_QFtarget_nested_parallel_privateEk_private_i32
+
+subroutine target_nested_parallel_private_num_threads(k)
+  integer :: k
+  !$omp target
+    !$omp parallel private(k) num_threads(k)
+      k = 10
+    !$omp end parallel
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_nested_parallel_private_num_threads
+! CHECK: omp.map.info {{.*}} name("k")
+! CHECK: omp.target
+! CHECK: omp.parallel {{.*}}private({{.*}}@_QFtarget_nested_parallel_private_num_threadsEk_private_i32
diff --git a/flang/test/Lower/OpenMP/target-parallel-private.f90 b/flang/test/Lower/OpenMP/target-parallel-private.f90
index f1b7959cee83be..0aba046585bcfb 100644
--- a/flang/test/Lower/OpenMP/target-parallel-private.f90
+++ b/flang/test/Lower/OpenMP/target-parallel-private.f90
@@ -15,7 +15,7 @@ subroutine target_parallel_private()
 
 ! CHECK: omp.private {type = private} @[[PRIVATIZER:.*]] : {{.*}}
 
-! CHECK: omp.target kernel_type(generic) {{.*}} {
+! CHECK: omp.target kernel_type(generic) {
 ! CHECK:   omp.parallel private(@[[PRIVATIZER]] %{{.*}} -> %{{.*}} : {{.*}}) {
 ! CHECK:   }
 ! CHECK: }
diff --git a/flang/test/Lower/OpenMP/target-scope.f90 b/flang/test/Lower/OpenMP/target-scope.f90
index 888e7ca3a00d28..8121dacf48f78a 100644
--- a/flang/test/Lower/OpenMP/target-scope.f90
+++ b/flang/test/Lower/OpenMP/target-scope.f90
@@ -62,10 +62,11 @@ subroutine target_scope_private()
   i = 0
 
   !$omp target
-    ! CHECK: omp.target kernel_type(generic) map_entries(%{{.*}} -> %[[IARG:.*]] : !fir.ref<i32>) {
-    ! CHECK:   hlfir.declare %[[IARG]] uniq_name("_QFtarget_scope_privateEi")
-    ! CHECK:   omp.scope private(@_QFtarget_scope_privateEi_private_i32 %{{.*}}#0 -> %[[PRIV:.*]] : !fir.ref<i32>) {
-    ! CHECK:     %[[PDECL:.*]]:2 = hlfir.declare %[[PRIV]] uniq_name("_QFtarget_scope_privateEi")
+    ! CHECK: omp.target kernel_type(generic) {
+    ! CHECK:   %[[IALLOCA:.*]] = fir.alloca i32 {bindc_name = "i", pinned, uniq_name = "_QFtarget_scope_privateEi"}
+    ! CHECK:   %[[IDECL:.*]]:2 = hlfir.declare %[[IALLOCA]] {uniq_name = "_QFtarget_scope_privateEi"}
+    ! CHECK:   omp.scope private(@_QFtarget_scope_privateEi_private_i32 %[[IDECL]]#0 -> %[[PRIV:.*]] : !fir.ref<i32>) {
+    ! CHECK:     %[[PDECL:.*]]:2 = hlfir.declare %[[PRIV]] {uniq_name = "_QFtarget_scope_privateEi"}
     !$omp scope private(i)
     ! CHECK:     hlfir.assign %{{.*}} to %[[PDECL]]#0 : i32, !fir.ref<i32>
     i = 42
diff --git a/flang/test/Lower/OpenMP/target-teams-private.f90 b/flang/test/Lower/OpenMP/target-teams-private.f90
index 6947e46e9c1e32..00996b06766df4 100644
--- a/flang/test/Lower/OpenMP/target-teams-private.f90
+++ b/flang/test/Lower/OpenMP/target-teams-private.f90
@@ -13,7 +13,7 @@ subroutine target_teams_private()
 !$omp end target teams
 end subroutine
 
-! CHECK: omp.target kernel_type(generic) {{.*}} {
+! CHECK: omp.target kernel_type(generic) {
 ! CHECK:   omp.teams {
 ! CHECK:     %{{.*}} = fir.alloca !fir.array<3xi32> <{bindc_name = "i", {{.*}}}>
 ! CHECK:   }
diff --git a/offload/test/offloading/fortran/target-composite-private-host-eval-map.f90 b/offload/test/offloading/fortran/target-composite-private-host-eval-map.f90
new file mode 100644
index 00000000000000..3817b0046e1d42
--- /dev/null
+++ b/offload/test/offloading/fortran/target-composite-private-host-eval-map.f90
@@ -0,0 +1,62 @@
+! Test that host-evaluated clause operands are still available when the
+! referenced scalar is also privatized on an inner leaf of a composite target
+! construct. Indicating that we have not optimized the implicit map out due
+! to privatization.
+!
+! REQUIRES: flang, amdgpu
+
+! RUN: %libomptarget-compile-fortran-run-and-check-generic
+! XFAIL: intelgpu
+
+program main
+  implicit none
+  integer :: errors
+
+  errors = 0
+
+  call check_parallel_do_num_threads(4, errors)
+  call check_teams_num_teams(4, errors)
+
+  print *, "errors:", errors
+
+contains
+  subroutine check_parallel_do_num_threads(n, errors)
+    use omp_lib
+    implicit none
+    integer :: n
+    integer, intent(inout) :: errors
+    integer :: observed
+    integer :: i
+
+    observed = -1
+    !$omp target parallel do private(n) num_threads(n) map(tofrom: observed)
+    do i = 1, 1
+      observed = omp_get_num_threads()
+      n = 99
+    end do
+    !$omp end target parallel do
+
+    if (observed .ne. n) errors = errors + 1
+  end subroutine
+
+  subroutine check_teams_num_teams(n, errors)
+    use omp_lib
+    implicit none
+    integer :: n
+    integer, intent(inout) :: errors
+    integer :: observed
+    integer :: i
+
+    observed = -1
+    !$omp target teams distribute private(n) num_teams(n) map(tofrom: observed)
+    do i = 1, 1
+      observed = omp_get_num_teams()
+      n = 99
+    end do
+    !$omp end target teams distribute
+
+    if (observed .ne. n) errors = errors + 1
+  end subroutine
+end program main
+
+! CHECK: errors: 0

>From b7e65788e578709be6cc3f9ebccd0d0ebb12a05c Mon Sep 17 00:00:00 2001
From: agozillon <Andrew.Gozillon at amd.com>
Date: Fri, 23 Oct 2026 14:58:35 -0500
Subject: [PATCH 2/3] Update stale tests after rebase

---
 .../target-composite-private-edge-cases.f90   |   2 +-
 ...target-composite-private-host-eval-map.f90 |   6 +-
 .../target-composite-private-unified.f90      | 220 +++++++++---------
 .../OpenMP/target-nested-private-unified.f90  |  30 +--
 .../Lower/OpenMP/target-nested-private.f90    |   4 +-
 flang/test/Lower/OpenMP/target-scope.f90      |   6 +-
 6 files changed, 134 insertions(+), 134 deletions(-)

diff --git a/flang/test/Lower/OpenMP/target-composite-private-edge-cases.f90 b/flang/test/Lower/OpenMP/target-composite-private-edge-cases.f90
index 5b280a4ae74c23..dddada21463e1b 100644
--- a/flang/test/Lower/OpenMP/target-composite-private-edge-cases.f90
+++ b/flang/test/Lower/OpenMP/target-composite-private-edge-cases.f90
@@ -101,7 +101,7 @@ subroutine target_parallel_do_private_array_shape()
 ! CHECK-NOT: omp.map.info {{.*}} name("arr")
 ! CHECK: omp.map.info {{.*}} name("out")
 ! CHECK: omp.target
-! CHECK: fir.alloca !fir.array<4xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_parallel_do_private_array_shapeEarr"}
+! CHECK: fir.alloca !fir.array<4xi32> <{bindc_name = "arr", pinned, uniq_name = "_QFtarget_parallel_do_private_array_shapeEarr"}>
 ! CHECK: omp.wsloop private(
 ! CHECK-SAME: @_QFtarget_parallel_do_private_array_shapeEarr_private_4xi32
 
diff --git a/flang/test/Lower/OpenMP/target-composite-private-host-eval-map.f90 b/flang/test/Lower/OpenMP/target-composite-private-host-eval-map.f90
index a48c9963b77c03..de773205b7f539 100644
--- a/flang/test/Lower/OpenMP/target-composite-private-host-eval-map.f90
+++ b/flang/test/Lower/OpenMP/target-composite-private-host-eval-map.f90
@@ -16,7 +16,7 @@ subroutine target_parallel_do_private_num_threads(n, out)
 ! CHECK: %[[N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
 ! CHECK: %[[I_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("i")
 ! CHECK: omp.target kernel_type(spmd) host_eval({{.*}}, %[[N_VAL]] -> %[[N_HOST_ARG:arg[0-9]+]] : {{.*}}) map_entries(%[[OUT_MAP]] -> %{{.*}}, %[[N_MAP]] -> %[[N_MAP_ARG:arg[0-9]+]], %[[I_MAP]] -> %{{.*}} : {{.*}}) {
-! CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %[[N_MAP_ARG]] {uniq_name = "_QFtarget_parallel_do_private_num_threadsEn"}
+! CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %[[N_MAP_ARG]] uniq_name("_QFtarget_parallel_do_private_num_threadsEn")
 ! CHECK: omp.parallel num_threads(%[[N_HOST_ARG]] : i32) {
 ! CHECK: omp.wsloop private({{.*}}@_QFtarget_parallel_do_private_num_threadsEn_private_i32 %[[N_DECL]]#0 -> %arg{{[0-9]+}}
 
@@ -35,7 +35,7 @@ subroutine target_teams_distribute_private_thread_limit(n, out)
 ! CHECK: %[[N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
 ! CHECK: %[[I_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("i")
 ! CHECK: omp.target kernel_type(generic) host_eval({{.*}}) map_entries(%[[OUT_MAP]] -> %{{.*}}, %[[N_MAP]] -> %[[N_MAP_ARG:arg[0-9]+]], %[[I_MAP]] -> %{{.*}} : {{.*}}) {
-! CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %[[N_MAP_ARG]] {uniq_name = "_QFtarget_teams_distribute_private_thread_limitEn"}
+! CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %[[N_MAP_ARG]] uniq_name("_QFtarget_teams_distribute_private_thread_limitEn")
 ! CHECK: %[[N_LOAD:.*]] = fir.load %[[N_DECL]]#0 : !fir.ref<i32>
 ! CHECK: omp.teams thread_limit(%[[N_LOAD]] : i32) {
 ! CHECK: omp.distribute private({{.*}}@_QFtarget_teams_distribute_private_thread_limitEn_private_i32 %[[N_DECL]]#0 -> %arg{{[0-9]+}}
@@ -56,6 +56,6 @@ subroutine target_teams_distribute_private_num_teams(n, out)
 ! CHECK: %[[N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
 ! CHECK: %[[I_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("i")
 ! CHECK: omp.target kernel_type(generic) host_eval({{.*}}, %[[N_VAL]] -> %[[N_HOST_ARG:arg[0-9]+]] : {{.*}}) map_entries(%[[OUT_MAP]] -> %{{.*}}, %[[N_MAP]] -> %[[N_MAP_ARG:arg[0-9]+]], %[[I_MAP]] -> %{{.*}} : {{.*}}) {
-! CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %[[N_MAP_ARG]] {uniq_name = "_QFtarget_teams_distribute_private_num_teamsEn"}
+! CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %[[N_MAP_ARG]] uniq_name("_QFtarget_teams_distribute_private_num_teamsEn")
 ! CHECK: omp.teams num_teams( to %[[N_HOST_ARG]] : i32) {
 ! CHECK: omp.distribute private({{.*}}@_QFtarget_teams_distribute_private_num_teamsEn_private_i32 %[[N_DECL]]#0 -> %arg{{[0-9]+}}
diff --git a/flang/test/Lower/OpenMP/target-composite-private-unified.f90 b/flang/test/Lower/OpenMP/target-composite-private-unified.f90
index 1b0798d6d7561e..64a722e82ef7fd 100644
--- a/flang/test/Lower/OpenMP/target-composite-private-unified.f90
+++ b/flang/test/Lower/OpenMP/target-composite-private-unified.f90
@@ -33,38 +33,38 @@ subroutine target_teams(n, assumed)
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr")
 ! CHECK-NOT: omp.map.info {{.*}} name("d")
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
-! CHECK: %[[TEAMS_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TEAMS_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc")
 ! CHECK: %[[TEAMS_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TEAMS_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
 ! CHECK: %[[TEAMS_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
 ! CHECK: %[[TEAMS_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
-! CHECK: %[[TEAMS_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TEAMS_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("assumed")
 ! CHECK: %[[TEAMS_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[TEAMS_ASSUMED_MEMBER]] {{.*}}) name("assumed")
 ! CHECK: %[[TEAMS_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
-! CHECK: %[[TEAMS_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TEAMS_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc_arr")
 ! CHECK: %[[TEAMS_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TEAMS_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
 ! CHECK: %[[TEAMS_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
 ! CHECK: %[[TEAMS_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
 ! CHECK: %[[TEAMS_AUTO_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("auto_arr")
 ! CHECK: %[[TEAMS_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("")
 ! CHECK: omp.target kernel_type(generic) map_entries(%[[TEAMS_ALLOC_MAP]] -> %{{.*}}, %[[TEAMS_DA_MAP]] -> %{{.*}}, %[[TEAMS_ASSUMED_MAP]] -> %{{.*}}, %[[TEAMS_ALLOC_ARR_MAP]] -> %{{.*}}, %[[TEAMS_DAA_MAP]] -> %{{.*}}, %[[TEAMS_AUTO_ARR_MAP]] -> %{{.*}}, %[[TEAMS_N_MAP]] -> %{{.*}}, %[[TEAMS_ALLOC_ATTACH]] -> %{{.*}}, %[[TEAMS_ASSUMED_ATTACH]] -> %{{.*}}, %[[TEAMS_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[TEAMS_ALLOC_MEMBER]] -> %{{.*}}, %[[TEAMS_ASSUMED_MEMBER]] -> %{{.*}}, %[[TEAMS_ALLOC_ARR_MEMBER]] -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) {
-! CHECK: hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teamsEalloc"}
-! CHECK: hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teamsEda"}
-! CHECK: hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teamsEassumed"}
-! CHECK: hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teamsEalloc_arr"}
-! CHECK: hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teamsEdaa"}
-! CHECK: hlfir.declare %arg{{[0-9]+}}(%{{.*}}) {uniq_name = "_QFtarget_teamsEauto_arr"}
+! CHECK: hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teamsEalloc") fortran_attrs<allocatable>
+! CHECK: hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teamsEda")
+! CHECK: hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teamsEassumed")
+! CHECK: hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teamsEalloc_arr") fortran_attrs<allocatable>
+! CHECK: hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teamsEdaa")
+! CHECK: hlfir.declare %arg{{[0-9]+}}(%{{.*}}) uniq_name("_QFtarget_teamsEauto_arr")
 ! CHECK: omp.teams {
-! CHECK: fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFtarget_teamsEs"}
-! CHECK: fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_teamsEarr"}
-! CHECK: fir.alloca !fir.box<!fir.heap<i32>> {bindc_name = "alloc", pinned, uniq_name = "_QFtarget_teamsEalloc"}
-! CHECK: fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFtarget_teamsEptr"}
-! CHECK: fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFtarget_teamsEd"}
-! CHECK: fir.alloca !fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}> {bindc_name = "da", pinned, uniq_name = "_QFtarget_teamsEda"}
-! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} {bindc_name = "assumed", pinned, uniq_name = "_QFtarget_teamsEassumed"}
-! CHECK: fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = "alloc_arr", pinned, uniq_name = "_QFtarget_teamsEalloc_arr"}
-! CHECK: fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_teamsEptr_arr"}
-! CHECK: fir.alloca !fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}> {bindc_name = "daa", pinned, uniq_name = "_QFtarget_teamsEdaa"}
-! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} {bindc_name = "auto_arr", pinned, uniq_name = "_QFtarget_teamsEauto_arr"}
+! CHECK: fir.alloca i32 <{bindc_name = "s", pinned, uniq_name = "_QFtarget_teamsEs"}>
+! CHECK: fir.alloca !fir.array<10xi32> <{bindc_name = "arr", pinned, uniq_name = "_QFtarget_teamsEarr"}>
+! CHECK: fir.alloca !fir.box<!fir.heap<i32>> <{bindc_name = "alloc", pinned, uniq_name = "_QFtarget_teamsEalloc"}>
+! CHECK: fir.alloca !fir.box<!fir.ptr<i32>> <{bindc_name = "ptr", pinned, uniq_name = "_QFtarget_teamsEptr"}>
+! CHECK: fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> <{bindc_name = "d", pinned, uniq_name = "_QFtarget_teamsEd"}>
+! CHECK: fir.alloca !fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}> <{bindc_name = "da", pinned, uniq_name = "_QFtarget_teamsEda"}>
+! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} <{bindc_name = "assumed", pinned, uniq_name = "_QFtarget_teamsEassumed"}>
+! CHECK: fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> <{bindc_name = "alloc_arr", pinned, uniq_name = "_QFtarget_teamsEalloc_arr"}>
+! CHECK: fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> <{bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_teamsEptr_arr"}>
+! CHECK: fir.alloca !fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}> <{bindc_name = "daa", pinned, uniq_name = "_QFtarget_teamsEdaa"}>
+! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} <{bindc_name = "auto_arr", pinned, uniq_name = "_QFtarget_teamsEauto_arr"}>
 
 subroutine target_parallel(n, assumed)
   use types
@@ -86,41 +86,41 @@ subroutine target_parallel(n, assumed)
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr")
 ! CHECK-NOT: omp.map.info {{.*}} name("d")
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
-! CHECK: %[[PAR_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PAR_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc")
 ! CHECK: %[[PAR_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[PAR_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
 ! CHECK: %[[PAR_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
 ! CHECK: %[[PAR_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
-! CHECK: %[[PAR_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PAR_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("assumed")
 ! CHECK: %[[PAR_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[PAR_ASSUMED_MEMBER]] {{.*}}) name("assumed")
 ! CHECK: %[[PAR_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
-! CHECK: %[[PAR_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PAR_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc_arr")
 ! CHECK: %[[PAR_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[PAR_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
 ! CHECK: %[[PAR_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
 ! CHECK: %[[PAR_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
 ! CHECK: %[[PAR_AUTO_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("auto_arr")
 ! CHECK: %[[PAR_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("")
 ! CHECK: omp.target kernel_type(generic) map_entries(%[[PAR_ALLOC_MAP]] -> %{{.*}}, %[[PAR_DA_MAP]] -> %{{.*}}, %[[PAR_ASSUMED_MAP]] -> %{{.*}}, %[[PAR_ALLOC_ARR_MAP]] -> %{{.*}}, %[[PAR_DAA_MAP]] -> %{{.*}}, %[[PAR_AUTO_ARR_MAP]] -> %{{.*}}, %[[PAR_N_MAP]] -> %{{.*}}, %[[PAR_ALLOC_ATTACH]] -> %{{.*}}, %[[PAR_ASSUMED_ATTACH]] -> %{{.*}}, %[[PAR_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[PAR_ALLOC_MEMBER]] -> %{{.*}}, %[[PAR_ASSUMED_MEMBER]] -> %{{.*}}, %[[PAR_ALLOC_ARR_MEMBER]] -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) {
-! CHECK: %[[PAR_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_parallelEalloc"}
-! CHECK: %[[PAR_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallelEda"}
-! CHECK: %[[PAR_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallelEassumed"}
-! CHECK: %[[PAR_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_parallelEalloc_arr"}
-! CHECK: %[[PAR_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallelEdaa"}
-! CHECK: %[[PAR_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) {uniq_name = "_QFtarget_parallelEauto_arr"}
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "da", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "assumed", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc_arr", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "daa", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "auto_arr", pinned
-! CHECK: %[[PAR_S_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFtarget_parallelEs"}
+! CHECK: %[[PAR_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_parallelEalloc") fortran_attrs<allocatable>
+! CHECK: %[[PAR_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_parallelEda")
+! CHECK: %[[PAR_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_parallelEassumed")
+! CHECK: %[[PAR_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_parallelEalloc_arr") fortran_attrs<allocatable>
+! CHECK: %[[PAR_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_parallelEdaa")
+! CHECK: %[[PAR_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) uniq_name("_QFtarget_parallelEauto_arr")
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "alloc", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "da", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "assumed", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "alloc_arr", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "daa", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "auto_arr", pinned
+! CHECK: %[[PAR_S_ALLOCA:.*]] = fir.alloca i32 <{bindc_name = "s", pinned, uniq_name = "_QFtarget_parallelEs"}>
 ! CHECK: %[[PAR_S_DECL:.*]]:2 = hlfir.declare %[[PAR_S_ALLOCA]]
-! CHECK: %[[PAR_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_parallelEarr"}
+! CHECK: %[[PAR_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> <{bindc_name = "arr", pinned, uniq_name = "_QFtarget_parallelEarr"}>
 ! CHECK: %[[PAR_ARR_DECL:.*]]:2 = hlfir.declare %[[PAR_ARR_ALLOCA]]
-! CHECK: %[[PAR_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFtarget_parallelEptr"}
+! CHECK: %[[PAR_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> <{bindc_name = "ptr", pinned, uniq_name = "_QFtarget_parallelEptr"}>
 ! CHECK: %[[PAR_PTR_DECL:.*]]:2 = hlfir.declare %[[PAR_PTR_ALLOCA]]
-! CHECK: %[[PAR_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFtarget_parallelEd"}
+! CHECK: %[[PAR_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> <{bindc_name = "d", pinned, uniq_name = "_QFtarget_parallelEd"}>
 ! CHECK: %[[PAR_D_DECL:.*]]:2 = hlfir.declare %[[PAR_D_ALLOCA]]
-! CHECK: %[[PAR_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_parallelEptr_arr"}
+! CHECK: %[[PAR_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> <{bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_parallelEptr_arr"}>
 ! CHECK: %[[PAR_PTR_ARR_DECL:.*]]:2 = hlfir.declare %[[PAR_PTR_ARR_ALLOCA]]
 ! CHECK: fir.store %[[PAR_ASSUMED_DECL]]#0 to %[[PAR_ASSUMED_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
 ! CHECK: fir.store %[[PAR_AUTO_ARR_DECL]]#0 to %[[PAR_AUTO_ARR_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
@@ -159,14 +159,14 @@ subroutine target_teams_distribute(n, assumed)
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr")
 ! CHECK-NOT: omp.map.info {{.*}} name("d")
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
-! CHECK: %[[TTD_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTD_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc")
 ! CHECK: %[[TTD_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TTD_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
 ! CHECK: %[[TTD_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
 ! CHECK: %[[TTD_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
-! CHECK: %[[TTD_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTD_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("assumed")
 ! CHECK: %[[TTD_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[TTD_ASSUMED_MEMBER]] {{.*}}) name("assumed")
 ! CHECK: %[[TTD_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
-! CHECK: %[[TTD_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTD_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc_arr")
 ! CHECK: %[[TTD_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TTD_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
 ! CHECK: %[[TTD_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
 ! CHECK: %[[TTD_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
@@ -175,28 +175,28 @@ subroutine target_teams_distribute(n, assumed)
 ! CHECK: %[[TTD_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
 ! CHECK: %[[TTD_BOUND_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("")
 ! CHECK: omp.target kernel_type(generic) host_eval({{.*}}) map_entries(%[[TTD_ALLOC_MAP]] -> %{{.*}}, %[[TTD_DA_MAP]] -> %{{.*}}, %[[TTD_ASSUMED_MAP]] -> %{{.*}}, %[[TTD_ALLOC_ARR_MAP]] -> %{{.*}}, %[[TTD_DAA_MAP]] -> %{{.*}}, %[[TTD_AUTO_ARR_MAP]] -> %{{.*}}, %[[TTD_I_MAP]] -> %{{.*}}, %[[TTD_N_MAP]] -> %{{.*}}, %[[TTD_BOUND_N_MAP]] -> %{{.*}}, %[[TTD_ALLOC_ATTACH]] -> %{{.*}}, %[[TTD_ASSUMED_ATTACH]] -> %{{.*}}, %[[TTD_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[TTD_ALLOC_MEMBER]] -> %{{.*}}, %[[TTD_ASSUMED_MEMBER]] -> %{{.*}}, %[[TTD_ALLOC_ARR_MEMBER]] -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) {
-! CHECK: %[[TTD_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teams_distributeEalloc"}
-! CHECK: %[[TTD_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distributeEda"}
-! CHECK: %[[TTD_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distributeEassumed"}
-! CHECK: %[[TTD_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teams_distributeEalloc_arr"}
-! CHECK: %[[TTD_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distributeEdaa"}
-! CHECK: %[[TTD_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) {uniq_name = "_QFtarget_teams_distributeEauto_arr"}
-! CHECK: %[[TTD_I_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distributeEi"}
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "da", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "assumed", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc_arr", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "daa", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "auto_arr", pinned
-! CHECK: %[[TTD_S_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFtarget_teams_distributeEs"}
+! CHECK: %[[TTD_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distributeEalloc") fortran_attrs<allocatable>
+! CHECK: %[[TTD_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distributeEda")
+! CHECK: %[[TTD_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distributeEassumed")
+! CHECK: %[[TTD_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distributeEalloc_arr") fortran_attrs<allocatable>
+! CHECK: %[[TTD_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distributeEdaa")
+! CHECK: %[[TTD_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) uniq_name("_QFtarget_teams_distributeEauto_arr")
+! CHECK: %[[TTD_I_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distributeEi")
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "alloc", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "da", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "assumed", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "alloc_arr", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "daa", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "auto_arr", pinned
+! CHECK: %[[TTD_S_ALLOCA:.*]] = fir.alloca i32 <{bindc_name = "s", pinned, uniq_name = "_QFtarget_teams_distributeEs"}>
 ! CHECK: %[[TTD_S_DECL:.*]]:2 = hlfir.declare %[[TTD_S_ALLOCA]]
-! CHECK: %[[TTD_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_teams_distributeEarr"}
+! CHECK: %[[TTD_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> <{bindc_name = "arr", pinned, uniq_name = "_QFtarget_teams_distributeEarr"}>
 ! CHECK: %[[TTD_ARR_DECL:.*]]:2 = hlfir.declare %[[TTD_ARR_ALLOCA]]
-! CHECK: %[[TTD_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFtarget_teams_distributeEptr"}
+! CHECK: %[[TTD_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> <{bindc_name = "ptr", pinned, uniq_name = "_QFtarget_teams_distributeEptr"}>
 ! CHECK: %[[TTD_PTR_DECL:.*]]:2 = hlfir.declare %[[TTD_PTR_ALLOCA]]
-! CHECK: %[[TTD_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFtarget_teams_distributeEd"}
+! CHECK: %[[TTD_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> <{bindc_name = "d", pinned, uniq_name = "_QFtarget_teams_distributeEd"}>
 ! CHECK: %[[TTD_D_DECL:.*]]:2 = hlfir.declare %[[TTD_D_ALLOCA]]
-! CHECK: %[[TTD_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_teams_distributeEptr_arr"}
+! CHECK: %[[TTD_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> <{bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_teams_distributeEptr_arr"}>
 ! CHECK: %[[TTD_PTR_ARR_DECL:.*]]:2 = hlfir.declare %[[TTD_PTR_ARR_ALLOCA]]
 ! CHECK: omp.teams {
 ! CHECK: fir.store %[[TTD_ASSUMED_DECL]]#0 to %[[TTD_ASSUMED_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
@@ -235,18 +235,18 @@ subroutine target_only(n, assumed)
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr")
 ! CHECK-NOT: omp.map.info {{.*}} name("d")
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
-! CHECK: %[[ONLY_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) capture(ByRef) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>, i32) name("")
+! CHECK: %[[ONLY_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) capture(ByRef) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>, i32) name("alloc")
 ! CHECK: %[[ONLY_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, to) {{.*}} members(%[[ONLY_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>)
 ! CHECK: %[[ONLY_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>, i32)
 ! CHECK: %[[ONLY_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(tofrom) capture(ByRef) mapper(@_QMtypesTdt_alloc_omp_default_mapper)
-! CHECK: %[[ONLY_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("")
+! CHECK: %[[ONLY_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("assumed")
 ! CHECK: %[[ONLY_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, to) {{.*}} members(%[[ONLY_ASSUMED_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>)
 ! CHECK: %[[ONLY_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, i32)
-! CHECK: %[[ONLY_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("")
+! CHECK: %[[ONLY_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("alloc_arr")
 ! CHECK: %[[ONLY_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, to) {{.*}} members(%[[ONLY_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>)
 ! CHECK: %[[ONLY_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, i32)
 ! CHECK: %[[ONLY_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(tofrom) capture(ByRef) mapper(@_QMtypesTdt_alloc_arr_omp_default_mapper)
-! CHECK: %[[ONLY_AUTO_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("")
+! CHECK: %[[ONLY_AUTO_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} name("auto_arr")
 ! CHECK: %[[ONLY_AUTO_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, to) {{.*}} members(%[[ONLY_AUTO_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>)
 ! CHECK: %[[ONLY_AUTO_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, i32)
 ! CHECK: omp.target kernel_type(generic) map_entries(%[[ONLY_ALLOC_MAP]] -> %{{.*}}, %[[ONLY_DA_MAP]] -> %{{.*}}, %[[ONLY_ASSUMED_MAP]] -> %{{.*}}, %[[ONLY_ALLOC_ARR_MAP]] -> %{{.*}}, %[[ONLY_DAA_MAP]] -> %{{.*}}, %[[ONLY_AUTO_ARR_MAP]] -> %{{.*}}, %[[ONLY_ALLOC_ATTACH]] -> %{{.*}}, %[[ONLY_ASSUMED_ATTACH]] -> %{{.*}}, %[[ONLY_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[ONLY_AUTO_ARR_ATTACH]] -> %{{.*}}, %[[ONLY_ALLOC_MEMBER]] -> %{{.*}}, %[[ONLY_ASSUMED_MEMBER]] -> %{{.*}}, %[[ONLY_ALLOC_ARR_MEMBER]] -> %{{.*}}, %[[ONLY_AUTO_ARR_MEMBER]] -> %{{.*}} : {{.*}}) private(
@@ -284,14 +284,14 @@ subroutine target_nested(n, assumed)
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr")
 ! CHECK-NOT: omp.map.info {{.*}} name("d")
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
-! CHECK: %[[NEST_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[NEST_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc")
 ! CHECK: %[[NEST_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[NEST_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
 ! CHECK: %[[NEST_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
 ! CHECK: %[[NEST_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
-! CHECK: %[[NEST_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[NEST_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("assumed")
 ! CHECK: %[[NEST_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[NEST_ASSUMED_MEMBER]] {{.*}}) name("assumed")
 ! CHECK: %[[NEST_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
-! CHECK: %[[NEST_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[NEST_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc_arr")
 ! CHECK: %[[NEST_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[NEST_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
 ! CHECK: %[[NEST_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
 ! CHECK: %[[NEST_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
@@ -333,14 +333,14 @@ subroutine target_teams_distribute_simd(n, assumed)
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr")
 ! CHECK-NOT: omp.map.info {{.*}} name("d")
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
-! CHECK: %[[TTDS_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTDS_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc")
 ! CHECK: %[[TTDS_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TTDS_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
 ! CHECK: %[[TTDS_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
 ! CHECK: %[[TTDS_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
-! CHECK: %[[TTDS_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTDS_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("assumed")
 ! CHECK: %[[TTDS_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[TTDS_ASSUMED_MEMBER]] {{.*}}) name("assumed")
 ! CHECK: %[[TTDS_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
-! CHECK: %[[TTDS_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[TTDS_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc_arr")
 ! CHECK: %[[TTDS_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[TTDS_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
 ! CHECK: %[[TTDS_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
 ! CHECK: %[[TTDS_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
@@ -349,28 +349,28 @@ subroutine target_teams_distribute_simd(n, assumed)
 ! CHECK: %[[TTDS_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
 ! CHECK: %[[TTDS_BOUND_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("")
 ! CHECK: omp.target kernel_type(generic) host_eval({{.*}}) map_entries(%[[TTDS_ALLOC_MAP]] -> %{{.*}}, %[[TTDS_DA_MAP]] -> %{{.*}}, %[[TTDS_ASSUMED_MAP]] -> %{{.*}}, %[[TTDS_ALLOC_ARR_MAP]] -> %{{.*}}, %[[TTDS_DAA_MAP]] -> %{{.*}}, %[[TTDS_AUTO_ARR_MAP]] -> %{{.*}}, %[[TTDS_I_MAP]] -> %{{.*}}, %[[TTDS_N_MAP]] -> %{{.*}}, %[[TTDS_BOUND_N_MAP]] -> %{{.*}}, %[[TTDS_ALLOC_ATTACH]] -> %{{.*}}, %[[TTDS_ASSUMED_ATTACH]] -> %{{.*}}, %[[TTDS_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[TTDS_ALLOC_MEMBER]] -> %{{.*}}, %[[TTDS_ASSUMED_MEMBER]] -> %{{.*}}, %[[TTDS_ALLOC_ARR_MEMBER]] -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) {
-! CHECK: %[[TTDS_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teams_distribute_simdEalloc"}
-! CHECK: %[[TTDS_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distribute_simdEda"}
-! CHECK: %[[TTDS_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distribute_simdEassumed"}
-! CHECK: %[[TTDS_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_teams_distribute_simdEalloc_arr"}
-! CHECK: %[[TTDS_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distribute_simdEdaa"}
-! CHECK: %[[TTDS_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) {uniq_name = "_QFtarget_teams_distribute_simdEauto_arr"}
-! CHECK: %[[TTDS_I_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_teams_distribute_simdEi"}
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "da", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "assumed", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc_arr", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "daa", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "auto_arr", pinned
-! CHECK: %[[TTDS_S_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFtarget_teams_distribute_simdEs"}
+! CHECK: %[[TTDS_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distribute_simdEalloc") fortran_attrs<allocatable>
+! CHECK: %[[TTDS_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distribute_simdEda")
+! CHECK: %[[TTDS_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distribute_simdEassumed")
+! CHECK: %[[TTDS_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distribute_simdEalloc_arr") fortran_attrs<allocatable>
+! CHECK: %[[TTDS_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distribute_simdEdaa")
+! CHECK: %[[TTDS_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) uniq_name("_QFtarget_teams_distribute_simdEauto_arr")
+! CHECK: %[[TTDS_I_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_teams_distribute_simdEi")
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "alloc", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "da", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "assumed", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "alloc_arr", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "daa", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "auto_arr", pinned
+! CHECK: %[[TTDS_S_ALLOCA:.*]] = fir.alloca i32 <{bindc_name = "s", pinned, uniq_name = "_QFtarget_teams_distribute_simdEs"}>
 ! CHECK: %[[TTDS_S_DECL:.*]]:2 = hlfir.declare %[[TTDS_S_ALLOCA]]
-! CHECK: %[[TTDS_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_teams_distribute_simdEarr"}
+! CHECK: %[[TTDS_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> <{bindc_name = "arr", pinned, uniq_name = "_QFtarget_teams_distribute_simdEarr"}>
 ! CHECK: %[[TTDS_ARR_DECL:.*]]:2 = hlfir.declare %[[TTDS_ARR_ALLOCA]]
-! CHECK: %[[TTDS_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFtarget_teams_distribute_simdEptr"}
+! CHECK: %[[TTDS_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> <{bindc_name = "ptr", pinned, uniq_name = "_QFtarget_teams_distribute_simdEptr"}>
 ! CHECK: %[[TTDS_PTR_DECL:.*]]:2 = hlfir.declare %[[TTDS_PTR_ALLOCA]]
-! CHECK: %[[TTDS_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFtarget_teams_distribute_simdEd"}
+! CHECK: %[[TTDS_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> <{bindc_name = "d", pinned, uniq_name = "_QFtarget_teams_distribute_simdEd"}>
 ! CHECK: %[[TTDS_D_DECL:.*]]:2 = hlfir.declare %[[TTDS_D_ALLOCA]]
-! CHECK: %[[TTDS_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_teams_distribute_simdEptr_arr"}
+! CHECK: %[[TTDS_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> <{bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_teams_distribute_simdEptr_arr"}>
 ! CHECK: %[[TTDS_PTR_ARR_DECL:.*]]:2 = hlfir.declare %[[TTDS_PTR_ARR_ALLOCA]]
 ! CHECK: omp.teams {
 ! CHECK: fir.store %[[TTDS_ASSUMED_DECL]]#0 to %[[TTDS_ASSUMED_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
@@ -412,14 +412,14 @@ subroutine target_parallel_do(n, assumed)
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr")
 ! CHECK-NOT: omp.map.info {{.*}} name("d")
 ! CHECK-NOT: omp.map.info {{.*}} name("ptr_arr")
-! CHECK: %[[PDO_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PDO_ALLOC_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc")
 ! CHECK: %[[PDO_ALLOC_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[PDO_ALLOC_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) name("alloc")
 ! CHECK: %[[PDO_ALLOC_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc")
 ! CHECK: %[[PDO_DA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("da")
-! CHECK: %[[PDO_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PDO_ASSUMED_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("assumed")
 ! CHECK: %[[PDO_ASSUMED_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, target_param, private, attach) {{.*}} members(%[[PDO_ASSUMED_MEMBER]] {{.*}}) name("assumed")
 ! CHECK: %[[PDO_ASSUMED_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("assumed")
-! CHECK: %[[PDO_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("")
+! CHECK: %[[PDO_ALLOC_ARR_MEMBER:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("alloc_arr")
 ! CHECK: %[[PDO_ALLOC_ARR_MAP:.*]] = omp.map.info {{.*}} map_clauses(always, implicit, to) {{.*}} members(%[[PDO_ALLOC_ARR_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) name("alloc_arr")
 ! CHECK: %[[PDO_ALLOC_ARR_ATTACH:.*]] = omp.map.info {{.*}} map_clauses(attach, ref_ptr, ref_ptee) {{.*}} name("alloc_arr")
 ! CHECK: %[[PDO_DAA_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} name("daa")
@@ -428,28 +428,28 @@ subroutine target_parallel_do(n, assumed)
 ! CHECK: %[[PDO_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("n")
 ! CHECK: %[[PDO_BOUND_N_MAP:.*]] = omp.map.info {{.*}} map_clauses(implicit) capture(ByCopy) name("")
 ! CHECK: omp.target kernel_type(spmd) host_eval({{.*}}) map_entries(%[[PDO_ALLOC_MAP]] -> %{{.*}}, %[[PDO_DA_MAP]] -> %{{.*}}, %[[PDO_ASSUMED_MAP]] -> %{{.*}}, %[[PDO_ALLOC_ARR_MAP]] -> %{{.*}}, %[[PDO_DAA_MAP]] -> %{{.*}}, %[[PDO_AUTO_ARR_MAP]] -> %{{.*}}, %[[PDO_I_MAP]] -> %{{.*}}, %[[PDO_N_MAP]] -> %{{.*}}, %[[PDO_BOUND_N_MAP]] -> %{{.*}}, %[[PDO_ALLOC_ATTACH]] -> %{{.*}}, %[[PDO_ASSUMED_ATTACH]] -> %{{.*}}, %[[PDO_ALLOC_ARR_ATTACH]] -> %{{.*}}, %[[PDO_ALLOC_MEMBER]] -> %{{.*}}, %[[PDO_ASSUMED_MEMBER]] -> %{{.*}}, %[[PDO_ALLOC_ARR_MEMBER]] -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc{a:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.type<_QMtypesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) {
-! CHECK: %[[PDO_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_parallel_doEalloc"}
-! CHECK: %[[PDO_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallel_doEda"}
-! CHECK: %[[PDO_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallel_doEassumed"}
-! CHECK: %[[PDO_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_parallel_doEalloc_arr"}
-! CHECK: %[[PDO_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallel_doEdaa"}
-! CHECK: %[[PDO_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) {uniq_name = "_QFtarget_parallel_doEauto_arr"}
-! CHECK: %[[PDO_I_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} {uniq_name = "_QFtarget_parallel_doEi"}
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "da", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "assumed", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "alloc_arr", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "daa", pinned
-! CHECK-NOT: fir.alloca {{.*}} {bindc_name = "auto_arr", pinned
-! CHECK: %[[PDO_S_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFtarget_parallel_doEs"}
+! CHECK: %[[PDO_ALLOC_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_parallel_doEalloc") fortran_attrs<allocatable>
+! CHECK: %[[PDO_DA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_parallel_doEda")
+! CHECK: %[[PDO_ASSUMED_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_parallel_doEassumed")
+! CHECK: %[[PDO_ALLOC_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_parallel_doEalloc_arr") fortran_attrs<allocatable>
+! CHECK: %[[PDO_DAA_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_parallel_doEdaa")
+! CHECK: %[[PDO_AUTO_ARR_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}}(%{{.*}}) uniq_name("_QFtarget_parallel_doEauto_arr")
+! CHECK: %[[PDO_I_DECL:.*]]:2 = hlfir.declare %arg{{[0-9]+}} uniq_name("_QFtarget_parallel_doEi")
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "alloc", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "da", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "assumed", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "alloc_arr", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "daa", pinned
+! CHECK-NOT: fir.alloca {{.*}}> <{bindc_name = "auto_arr", pinned
+! CHECK: %[[PDO_S_ALLOCA:.*]] = fir.alloca i32 <{bindc_name = "s", pinned, uniq_name = "_QFtarget_parallel_doEs"}>
 ! CHECK: %[[PDO_S_DECL:.*]]:2 = hlfir.declare %[[PDO_S_ALLOCA]]
-! CHECK: %[[PDO_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFtarget_parallel_doEarr"}
+! CHECK: %[[PDO_ARR_ALLOCA:.*]] = fir.alloca !fir.array<10xi32> <{bindc_name = "arr", pinned, uniq_name = "_QFtarget_parallel_doEarr"}>
 ! CHECK: %[[PDO_ARR_DECL:.*]]:2 = hlfir.declare %[[PDO_ARR_ALLOCA]]
-! CHECK: %[[PDO_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFtarget_parallel_doEptr"}
+! CHECK: %[[PDO_PTR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> <{bindc_name = "ptr", pinned, uniq_name = "_QFtarget_parallel_doEptr"}>
 ! CHECK: %[[PDO_PTR_DECL:.*]]:2 = hlfir.declare %[[PDO_PTR_ALLOCA]]
-! CHECK: %[[PDO_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFtarget_parallel_doEd"}
+! CHECK: %[[PDO_D_ALLOCA:.*]] = fir.alloca !fir.type<_QMtypesTdt{a:i32,b:f32}> <{bindc_name = "d", pinned, uniq_name = "_QFtarget_parallel_doEd"}>
 ! CHECK: %[[PDO_D_DECL:.*]]:2 = hlfir.declare %[[PDO_D_ALLOCA]]
-! CHECK: %[[PDO_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_parallel_doEptr_arr"}
+! CHECK: %[[PDO_PTR_ARR_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> <{bindc_name = "ptr_arr", pinned, uniq_name = "_QFtarget_parallel_doEptr_arr"}>
 ! CHECK: %[[PDO_PTR_ARR_DECL:.*]]:2 = hlfir.declare %[[PDO_PTR_ARR_ALLOCA]]
 ! CHECK: omp.parallel {
 ! CHECK: fir.store %[[PDO_ASSUMED_DECL]]#0 to %[[PDO_ASSUMED_COPY:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
diff --git a/flang/test/Lower/OpenMP/target-nested-private-unified.f90 b/flang/test/Lower/OpenMP/target-nested-private-unified.f90
index 0ce63fba5c4401..a0b2dda3a55760 100644
--- a/flang/test/Lower/OpenMP/target-nested-private-unified.f90
+++ b/flang/test/Lower/OpenMP/target-nested-private-unified.f90
@@ -43,17 +43,17 @@ subroutine nested_target_teams(n, assumed)
 ! CHECK: omp.map.info {{.*}} name("auto_arr")
 ! CHECK: omp.target
 ! CHECK: omp.teams
-! CHECK: fir.alloca i32 {bindc_name = "s", pinned, uniq_name = "_QFnested_target_teamsEs"}
-! CHECK: fir.alloca !fir.array<10xi32> {bindc_name = "arr", pinned, uniq_name = "_QFnested_target_teamsEarr"}
-! CHECK: fir.alloca !fir.box<!fir.heap<i32>> {bindc_name = "alloc", pinned, uniq_name = "_QFnested_target_teamsEalloc"}
-! CHECK: fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "ptr", pinned, uniq_name = "_QFnested_target_teamsEptr"}
-! CHECK: fir.alloca !fir.type<_QMnested_private_typesTdt{a:i32,b:f32}> {bindc_name = "d", pinned, uniq_name = "_QFnested_target_teamsEd"}
-! CHECK: fir.alloca !fir.type<_QMnested_private_typesTdt_alloc{a:!fir.box<!fir.heap<i32>>}> {bindc_name = "da", pinned, uniq_name = "_QFnested_target_teamsEda"}
-! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} {bindc_name = "assumed", pinned, uniq_name = "_QFnested_target_teamsEassumed"}
-! CHECK: fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = "alloc_arr", pinned, uniq_name = "_QFnested_target_teamsEalloc_arr"}
-! CHECK: fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> {bindc_name = "ptr_arr", pinned, uniq_name = "_QFnested_target_teamsEptr_arr"}
-! CHECK: fir.alloca !fir.type<_QMnested_private_typesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}> {bindc_name = "daa", pinned, uniq_name = "_QFnested_target_teamsEdaa"}
-! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} {bindc_name = "auto_arr", pinned, uniq_name = "_QFnested_target_teamsEauto_arr"}
+! CHECK: fir.alloca i32 <{bindc_name = "s", pinned, uniq_name = "_QFnested_target_teamsEs"}>
+! CHECK: fir.alloca !fir.array<10xi32> <{bindc_name = "arr", pinned, uniq_name = "_QFnested_target_teamsEarr"}>
+! CHECK: fir.alloca !fir.box<!fir.heap<i32>> <{bindc_name = "alloc", pinned, uniq_name = "_QFnested_target_teamsEalloc"}>
+! CHECK: fir.alloca !fir.box<!fir.ptr<i32>> <{bindc_name = "ptr", pinned, uniq_name = "_QFnested_target_teamsEptr"}>
+! CHECK: fir.alloca !fir.type<_QMnested_private_typesTdt{a:i32,b:f32}> <{bindc_name = "d", pinned, uniq_name = "_QFnested_target_teamsEd"}>
+! CHECK: fir.alloca !fir.type<_QMnested_private_typesTdt_alloc{a:!fir.box<!fir.heap<i32>>}> <{bindc_name = "da", pinned, uniq_name = "_QFnested_target_teamsEda"}>
+! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} <{bindc_name = "assumed", pinned, uniq_name = "_QFnested_target_teamsEassumed"}>
+! CHECK: fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> <{bindc_name = "alloc_arr", pinned, uniq_name = "_QFnested_target_teamsEalloc_arr"}>
+! CHECK: fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> <{bindc_name = "ptr_arr", pinned, uniq_name = "_QFnested_target_teamsEptr_arr"}>
+! CHECK: fir.alloca !fir.type<_QMnested_private_typesTdt_alloc_arr{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}> <{bindc_name = "daa", pinned, uniq_name = "_QFnested_target_teamsEdaa"}>
+! CHECK: fir.alloca !fir.array<?xi32>, %{{.*}} <{bindc_name = "auto_arr", pinned, uniq_name = "_QFnested_target_teamsEauto_arr"}>
 
 subroutine nested_target_parallel(n, assumed)
   use nested_private_types
@@ -278,9 +278,9 @@ subroutine nested_target_parallel_both_private()
 ! CHECK-LABEL: func.func @_QPnested_target_parallel_both_private
 ! CHECK-NOT: omp.map.info {{.*}} name("k")
 ! CHECK: omp.target kernel_type(generic) private(@_QFnested_target_parallel_both_privateEk_private_i32 %{{.*}}#0 -> %[[TP_K_ARG:arg[0-9]+]] : !fir.ref<i32>) {
-! CHECK: %[[TP_K_DECL:.*]]:2 = hlfir.declare %[[TP_K_ARG]] {uniq_name = "_QFnested_target_parallel_both_privateEk"}
+! CHECK: %[[TP_K_DECL:.*]]:2 = hlfir.declare %[[TP_K_ARG]] uniq_name("_QFnested_target_parallel_both_privateEk")
 ! CHECK: omp.parallel private(@_QFnested_target_parallel_both_privateEk_private_i32 %[[TP_K_DECL]]#0 -> %[[PAR_K_ARG:arg[0-9]+]] : !fir.ref<i32>) {
-! CHECK: hlfir.declare %[[PAR_K_ARG]] {uniq_name = "_QFnested_target_parallel_both_privateEk"}
+! CHECK: hlfir.declare %[[PAR_K_ARG]] uniq_name("_QFnested_target_parallel_both_privateEk")
 
 subroutine nested_target_teams_distribute_both_private()
   integer :: i, k
@@ -298,7 +298,7 @@ subroutine nested_target_teams_distribute_both_private()
 ! CHECK: omp.map.info {{.*}} name("i")
 ! CHECK-NOT: omp.map.info {{.*}} name("k")
 ! CHECK: omp.target {{.*}}private(@_QFnested_target_teams_distribute_both_privateEk_private_i32 %{{.*}}#0 -> %[[TTD_K_ARG:arg[0-9]+]]
-! CHECK: %[[TTD_K_DECL:.*]]:2 = hlfir.declare %[[TTD_K_ARG]] {uniq_name = "_QFnested_target_teams_distribute_both_privateEk"}
+! CHECK: %[[TTD_K_DECL:.*]]:2 = hlfir.declare %[[TTD_K_ARG]] uniq_name("_QFnested_target_teams_distribute_both_privateEk")
 ! CHECK: omp.teams
 ! CHECK: omp.distribute private({{.*}}@_QFnested_target_teams_distribute_both_privateEk_private_i32 %[[TTD_K_DECL]]#0 -> %[[DIST_K_ARG:arg[0-9]+]]
-! CHECK: hlfir.declare %[[DIST_K_ARG]] {uniq_name = "_QFnested_target_teams_distribute_both_privateEk"}
+! CHECK: hlfir.declare %[[DIST_K_ARG]] uniq_name("_QFnested_target_teams_distribute_both_privateEk")
diff --git a/flang/test/Lower/OpenMP/target-nested-private.f90 b/flang/test/Lower/OpenMP/target-nested-private.f90
index a32cc72af118d5..a46559a8e6eb52 100644
--- a/flang/test/Lower/OpenMP/target-nested-private.f90
+++ b/flang/test/Lower/OpenMP/target-nested-private.f90
@@ -16,7 +16,7 @@ subroutine target_nested_teams_distribute_private()
 ! CHECK: omp.map.info {{.*}} name("i")
 ! CHECK-NOT: omp.map.info {{.*}} name("k")
 ! CHECK: omp.target
-! CHECK: fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFtarget_nested_teams_distribute_privateEk"}
+! CHECK: fir.alloca i32 <{bindc_name = "k", pinned, uniq_name = "_QFtarget_nested_teams_distribute_privateEk"}>
 ! CHECK: omp.teams
 ! CHECK: omp.distribute private({{.*}}@_QFtarget_nested_teams_distribute_privateEk_private_i32
 
@@ -49,7 +49,7 @@ subroutine target_nested_parallel_private()
 ! CHECK-LABEL: func.func @_QPtarget_nested_parallel_private
 ! CHECK-NOT: omp.map.info {{.*}} name("k")
 ! CHECK: omp.target
-! CHECK: fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFtarget_nested_parallel_privateEk"}
+! CHECK: fir.alloca i32 <{bindc_name = "k", pinned, uniq_name = "_QFtarget_nested_parallel_privateEk"}>
 ! CHECK: omp.parallel private({{.*}}@_QFtarget_nested_parallel_privateEk_private_i32
 
 subroutine target_nested_parallel_private_num_threads(k)
diff --git a/flang/test/Lower/OpenMP/target-scope.f90 b/flang/test/Lower/OpenMP/target-scope.f90
index 8121dacf48f78a..5606fd510f54ae 100644
--- a/flang/test/Lower/OpenMP/target-scope.f90
+++ b/flang/test/Lower/OpenMP/target-scope.f90
@@ -63,10 +63,10 @@ subroutine target_scope_private()
 
   !$omp target
     ! CHECK: omp.target kernel_type(generic) {
-    ! CHECK:   %[[IALLOCA:.*]] = fir.alloca i32 {bindc_name = "i", pinned, uniq_name = "_QFtarget_scope_privateEi"}
-    ! CHECK:   %[[IDECL:.*]]:2 = hlfir.declare %[[IALLOCA]] {uniq_name = "_QFtarget_scope_privateEi"}
+    ! CHECK:   %[[IALLOCA:.*]] = fir.alloca i32 <{bindc_name = "i", pinned, uniq_name = "_QFtarget_scope_privateEi"}>
+    ! CHECK:   %[[IDECL:.*]]:2 = hlfir.declare %[[IALLOCA]] uniq_name("_QFtarget_scope_privateEi")
     ! CHECK:   omp.scope private(@_QFtarget_scope_privateEi_private_i32 %[[IDECL]]#0 -> %[[PRIV:.*]] : !fir.ref<i32>) {
-    ! CHECK:     %[[PDECL:.*]]:2 = hlfir.declare %[[PRIV]] {uniq_name = "_QFtarget_scope_privateEi"}
+    ! CHECK:     %[[PDECL:.*]]:2 = hlfir.declare %[[PRIV]] uniq_name("_QFtarget_scope_privateEi")
     !$omp scope private(i)
     ! CHECK:     hlfir.assign %{{.*}} to %[[PDECL]]#0 : i32, !fir.ref<i32>
     i = 42

>From a47429eb0ebabdd583873e02836a2a3b071aba9b Mon Sep 17 00:00:00 2001
From: agozillon <Andrew.Gozillon at amd.com>
Date: Fri, 23 Oct 2026 18:06:12 -0500
Subject: [PATCH 3/3] Address review comments

---
 flang/lib/Lower/OpenMP/OpenMP.cpp             | 145 ++++++++----------
 flang/lib/Utils/OpenMP.cpp                    |   9 +-
 .../Lower/OpenMP/target-nested-private.f90    |  51 ++++++
 3 files changed, 118 insertions(+), 87 deletions(-)

diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 8f6a01e933fe8f..f11777a24a1298 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -188,6 +188,39 @@ static bool hasPrivatizedArrayElementReduction(
   return false;
 }
 
+/// Obtain the list of clauses of the given OpenMP block, loop or sections
+/// construct evaluation. If it's not an OpenMP construct, no modifications
+/// are made to the \c clauses output argument.
+void extractClauses(lower::pft::Evaluation &eval, List<Clause> &clauses,
+                    semantics::SemanticsContext &semaCtx) {
+  const auto *ompEval{eval.getIf<parser::OpenMPConstruct>()};
+  if (!ompEval)
+    return;
+
+  const parser::OmpClauseList *beginClauseList{nullptr};
+  const parser::OmpClauseList *endClauseList{nullptr};
+  common::visit(
+      [&](const auto &construct) {
+        using Type = llvm::remove_cvref_t<decltype(construct)>;
+        if constexpr (std::is_same_v<Type, parser::OmpBlockConstruct> ||
+                      std::is_same_v<Type, parser::OpenMPLoopConstruct> ||
+                      std::is_same_v<Type, parser::OpenMPSectionsConstruct>) {
+          beginClauseList = &construct.BeginDir().Clauses();
+          if (auto &endSpec{construct.EndDir()})
+            endClauseList = &endSpec->Clauses();
+        }
+      },
+      ompEval->u);
+
+  if (!beginClauseList)
+    return;
+
+  clauses.append(makeClauses(*beginClauseList, semaCtx));
+
+  if (endClauseList)
+    clauses.append(makeClauses(*endClauseList, semaCtx));
+}
+
 /// Structure holding the information needed to create and bind entry block
 /// arguments associated to a single clause during OpenMP lowering.
 struct ObjectEntryBlockArgsEntry {
@@ -430,36 +463,6 @@ class DirectivePatternVisitor {
   virtual llvm::omp::Directives visitDirective(lower::pft::Evaluation &eval,
                                                llvm::omp::Directive dir) = 0;
 
-  /// Obtain the list of clauses of the given OpenMP block, loop or sections
-  /// construct evaluation. If it's not an OpenMP construct, no modifications
-  /// are made to the \c clauses output argument.
-  void extractClauses(lower::pft::Evaluation &eval, List<Clause> &clauses) {
-    const auto *ompEval{eval.getIf<parser::OpenMPConstruct>()};
-    if (!ompEval)
-      return;
-
-    const parser::OmpClauseList *beginClauseList{nullptr};
-    const parser::OmpClauseList *endClauseList{nullptr};
-    common::visit(
-        [&](const auto &construct) {
-          using Type = llvm::remove_cvref_t<decltype(construct)>;
-          if constexpr (std::is_same_v<Type, parser::OmpBlockConstruct> ||
-                        std::is_same_v<Type, parser::OpenMPLoopConstruct> ||
-                        std::is_same_v<Type, parser::OpenMPSectionsConstruct>) {
-            beginClauseList = &construct.BeginDir().Clauses();
-            if (auto &endSpec{construct.EndDir()})
-              endClauseList = &endSpec->Clauses();
-          }
-        },
-        ompEval->u);
-
-    assert(beginClauseList && "expected begin directive");
-    clauses.append(makeClauses(*beginClauseList, semaCtx));
-
-    if (endClauseList)
-      clauses.append(makeClauses(*endClauseList, semaCtx));
-  }
-
 private:
   /// Decide whether an evaluation must be visited as part of the pattern.
   ///
@@ -554,7 +557,7 @@ class TargetSPMDVisitor : public DirectivePatternVisitor {
 
   bool hasOmpxBareClause(lower::pft::Evaluation &eval) {
     List<lower::omp::Clause> clauses;
-    extractClauses(eval, clauses);
+    extractClauses(eval, clauses, semaCtx);
 
     return llvm::find_if(clauses, [](const Clause &clause) {
              return std::holds_alternative<clause::OmpxBare>(clause.u);
@@ -599,7 +602,7 @@ class HostEvalVisitor : public TargetSPMDVisitor {
     using namespace llvm::omp;
 
     List<lower::omp::Clause> clauses;
-    extractClauses(eval, clauses);
+    extractClauses(eval, clauses, semaCtx);
     ClauseProcessor cp{converter, semaCtx, clauses};
 
     // Currently, we deal differently with e.g. `target parallel workshare` to
@@ -784,7 +787,7 @@ class KernelTypeVisitor : protected TargetSPMDVisitor {
 private:
   bool canPromoteSPMDToNoLoop(lower::pft::Evaluation &eval) {
     List<lower::omp::Clause> clauses;
-    extractClauses(eval, clauses);
+    extractClauses(eval, clauses, semaCtx);
 
     // First make sure the proper module attributes are present in order to
     // perform this optimization.
@@ -2193,7 +2196,13 @@ static void genBodyOfTargetOp(
   // Materialize region-local copies for the private list items of inner leaf
   // constructs (e.g. distribute) of a combined/composite target directive,
   // with the intent of replacing a host to device data-mapping (map info
-  // emission). Teams already performs this materialization itself.
+  // emission). Teams already performs this materialization itself as it opts
+  // out of the regular delayed privatization path for the moment, but there
+  // are plans to change this in the future. When this occurs, we must adjust
+  // this.
+  // TODO: When teams undergoes its delayed privatization update we will need
+  // to remove this edge case handling and let it proceed like all of the other
+  // cases.
   if (!targetNestedPrivateInfo.innermostLeafIsTeams)
     for (const semantics::Symbol *sym : targetNestedPrivateInfo.syms)
       converter.createHostAssociateVarClone(*sym, /*skipDefaultInit=*/false);
@@ -2222,7 +2231,7 @@ static void genBodyOfTargetOp(
     genNestedEvaluations(converter, eval);
   }
 
-  // When materializing arrays inside of the target region for composite
+  // When materializing arrays inside of the target region for compound
   // directives with leaf-bound private clauses, we can end up with the
   // constants populating the shape being bound to constants external to the
   // target region. Perform a final clone-only repair to resolve these without
@@ -4058,36 +4067,6 @@ findInnermostPrivateLeaf(ConstructQueue::const_iterator begin,
   return queue.end();
 }
 
-static List<Clause>
-getOpenMPConstructClauses(const parser::OpenMPConstruct &ompEval,
-                          semantics::SemanticsContext &semaCtx) {
-  List<Clause> clauses;
-  const parser::OmpClauseList *beginClauseList{nullptr};
-  const parser::OmpClauseList *endClauseList{nullptr};
-
-  common::visit(
-      [&](const auto &construct) {
-        using Type = llvm::remove_cvref_t<decltype(construct)>;
-        if constexpr (std::is_same_v<Type, parser::OmpBlockConstruct> ||
-                      std::is_same_v<Type, parser::OpenMPLoopConstruct>) {
-          beginClauseList = &construct.BeginDir().Clauses();
-          if (auto &endSpec{construct.EndDir()})
-            endClauseList = &endSpec->Clauses();
-        }
-      },
-      ompEval.u);
-
-  if (!beginClauseList)
-    return clauses;
-
-  clauses.append(makeClauses(*beginClauseList, semaCtx));
-
-  if (endClauseList)
-    clauses.append(makeClauses(*endClauseList, semaCtx));
-
-  return clauses;
-}
-
 static bool isSymbolUsedInClauseRange(const semantics::Symbol &target,
                                       ConstructQueue::const_iterator begin,
                                       ConstructQueue::const_iterator end,
@@ -4132,14 +4111,13 @@ static bool isSymbolUsedInClauseRange(const semantics::Symbol &target,
 // region. Types that still need a map just to populate the initial state are
 // allocatables, derived types with allocatable or pointer ultimate components,
 // assumed-shape arrays, automatic arrays, and common block members. Currently
-// we leave these as they were before, but in the future we can minimize the
-// mapping by sending across exactly what is required to be specification
-// compliant.
-static bool isTargetLocalCloneable(const semantics::Symbol &sym,
-                                   semantics::SemanticsContext &semaCtx) {
-  const semantics::Symbol &ult = sym.GetUltimate();
+// we still initialize these, but in the future we can minimize the mapping by
+// sending across exactly what is required to be specification compliant.
+static bool isTargetValueLocalCloneable(const semantics::Symbol &valueSymbol,
+                                        semantics::SemanticsContext &semaCtx) {
+  const semantics::Symbol &ult = valueSymbol.GetUltimate();
 
-  if (Fortran::semantics::FindCommonBlockContaining(ult))
+  if (semantics::FindCommonBlockContaining(ult))
     return false;
 
   if (semantics::IsAllocatable(ult))
@@ -4166,16 +4144,16 @@ static bool isTargetLocalCloneable(const semantics::Symbol &sym,
   return true;
 }
 
-static bool isExplicitlyMapped(const semantics::Symbol &sym,
-                               llvm::ArrayRef<Object> mapObjects) {
+static bool objectListContainsSymbol(const semantics::Symbol &sym,
+                                     llvm::ArrayRef<Object> objects) {
   const semantics::Symbol &ult = sym.GetUltimate();
-  return llvm::any_of(mapObjects, [&](const Object &object) {
+  return llvm::any_of(objects, [&](const Object &object) {
     return object.sym() && object.sym()->GetUltimate() == ult;
   });
 }
 
-static bool isAlreadyPrivatizedOnTarget(const semantics::Symbol &sym,
-                                        const DataSharingProcessor &dsp) {
+static bool isAlreadyPrivatized(const semantics::Symbol &sym,
+                                const DataSharingProcessor &dsp) {
   const semantics::Symbol &ult = sym.GetUltimate();
   return llvm::any_of(dsp.getAllSymbolsToPrivatize(),
                       [&](const semantics::Symbol *priv) {
@@ -4196,14 +4174,14 @@ static void collectTargetNestedPrivateSymsFromLeaf(
         const semantics::Symbol *sym = object.sym();
         if (!sym)
           continue;
-        if (isExplicitlyMapped(*sym, mapObjects))
+        if (objectListContainsSymbol(*sym, mapObjects))
           continue;
-        if (excludePrivatizedSyms && isAlreadyPrivatizedOnTarget(*sym, dsp))
+        if (excludePrivatizedSyms && isAlreadyPrivatized(*sym, dsp))
           continue;
         if (isSymbolUsedInClauseRange(*sym, begin, end,
                                       /*ignorePrivateAndMap=*/true))
           continue;
-        if (!isTargetLocalCloneable(*sym, semaCtx))
+        if (!isTargetValueLocalCloneable(*sym, semaCtx))
           continue;
         result.syms.push_back(sym);
       }
@@ -4250,10 +4228,15 @@ static TargetNestedPrivateInfo collectTargetNestedPrivateSyms(
   if (!nestedEval)
     return result;
 
+  while (lower::pft::Evaluation *nextEval =
+             extractOnlyOmpNestedEval(*nestedEval))
+    nestedEval = nextEval;
+
   const auto &ompEval = nestedEval->get<parser::OpenMPConstruct>();
   parser::OmpDirectiveName nestedName =
       parser::omp::GetOmpDirectiveName(ompEval);
-  List<Clause> nestedClauses = getOpenMPConstructClauses(ompEval, semaCtx);
+  List<lower::omp::Clause> nestedClauses;
+  extractClauses(*nestedEval, nestedClauses, semaCtx);
   if (!llvm::any_of(nestedClauses, [](const Clause &clause) {
         return std::holds_alternative<clause::Private>(clause.u);
       }))
diff --git a/flang/lib/Utils/OpenMP.cpp b/flang/lib/Utils/OpenMP.cpp
index 0a8c5bca578665..3bc92b97d7dd9b 100644
--- a/flang/lib/Utils/OpenMP.cpp
+++ b/flang/lib/Utils/OpenMP.cpp
@@ -214,12 +214,9 @@ void cloneOrMapRegionOutsiders(fir::FirOpBuilder &firOpBuilder,
     valuesDefinedAbove.clear();
     mlir::getUsedValuesDefinedAbove(region, valuesDefinedAbove);
 
-    if (!canEmitMaps && !valuesDefinedAbove.empty() && !madeProgress) {
-      assert(false &&
-          "failed to clone all values used in the target region but defined "
-          "above it");
-      break;
-    }
+    assert((canEmitMaps || valuesDefinedAbove.empty() || madeProgress) &&
+        "failed to clone all values used in the target region but defined "
+        "above it");
   }
 }
 
diff --git a/flang/test/Lower/OpenMP/target-nested-private.f90 b/flang/test/Lower/OpenMP/target-nested-private.f90
index a46559a8e6eb52..ea5775532fbc5a 100644
--- a/flang/test/Lower/OpenMP/target-nested-private.f90
+++ b/flang/test/Lower/OpenMP/target-nested-private.f90
@@ -65,3 +65,54 @@ subroutine target_nested_parallel_private_num_threads(k)
 ! CHECK: omp.map.info {{.*}} name("k")
 ! CHECK: omp.target
 ! CHECK: omp.parallel {{.*}}private({{.*}}@_QFtarget_nested_parallel_private_num_threadsEk_private_i32
+
+program main
+  implicit none
+  integer :: i, n
+
+  !$omp target
+    !$omp teams
+      !$omp distribute private(i)
+      do i = 1, n
+      end do
+    !$omp end teams
+  !$omp end target
+end program
+
+! CHECK-LABEL: func.func @_QQmain
+! CHECK-NOT: omp.map.info {{.*}} name("i")
+! CHECK: omp.map.info {{.*}} name("n")
+! CHECK-NOT: omp.map.info {{.*}} name("i")
+! CHECK: omp.target
+! CHECK: %[[I_ALLOCA:.*]] = fir.alloca i32 <{bindc_name = "i", pinned, uniq_name = "_QFEi"}>
+! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I_ALLOCA]] uniq_name("_QFEi")
+! CHECK: omp.teams
+! CHECK: omp.distribute private({{.*}}@_QFEi_private_i32 %[[I_DECL]]#0 -> %[[I_PRIV_ARG:.*]] : !fir.ref<i32>)
+! CHECK: omp.loop_nest
+! CHECK: hlfir.declare %[[I_PRIV_ARG]] uniq_name("_QFEi")
+
+subroutine target_teams_distribute_nested_parallel_private(n)
+  implicit none
+  integer :: i, n
+
+  !$omp target teams
+    !$omp distribute
+    do i = 1, n
+      !$omp parallel private(i)
+      !$omp end parallel
+    end do
+  !$omp end target teams
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtarget_teams_distribute_nested_parallel_private
+! CHECK: %[[I_MAP:.*]] = omp.map.info {{.*}} name("i")
+! CHECK: %[[N_MAP:.*]] = omp.map.info {{.*}} name("n")
+! CHECK: omp.target {{.*}}map_entries(%[[I_MAP]] -> %[[I_MAP_ARG:.*]], %[[N_MAP]] -> %{{.*}} : !fir.ref<i32>, !fir.ref<i32>)
+! CHECK-NEXT: %[[I_TARGET_DECL:.*]]:2 = hlfir.declare %[[I_MAP_ARG]] uniq_name("_QFtarget_teams_distribute_nested_parallel_privateEi")
+! CHECK-NOT: fir.alloca i32 <{bindc_name = "i", pinned, uniq_name = "_QFtarget_teams_distribute_nested_parallel_privateEi"}>
+! CHECK: omp.teams
+! CHECK: omp.distribute private({{.*}}@_QFtarget_teams_distribute_nested_parallel_privateEi_private_i32 %[[I_TARGET_DECL]]#0 -> %[[I_DIST_ARG:.*]] : !fir.ref<i32>)
+! CHECK: omp.loop_nest
+! CHECK: hlfir.declare %[[I_DIST_ARG]] uniq_name("_QFtarget_teams_distribute_nested_parallel_privateEi")
+! CHECK: omp.parallel private({{.*}}@_QFtarget_teams_distribute_nested_parallel_privateEi_private_i32 {{.*}} -> %[[I_PAR_ARG:.*]] : !fir.ref<i32>)
+! CHECK: hlfir.declare %[[I_PAR_ARG]] uniq_name("_QFtarget_teams_distribute_nested_parallel_privateEi")



More information about the flang-commits mailing list