[flang-commits] [flang] [flang][OpenMP][DoConcurrent] Emit declare mapper for records (PR #179936)

Kareem Ergawy via flang-commits flang-commits at lists.llvm.org
Mon Mar 9 08:33:15 PDT 2026


https://github.com/ergawy updated https://github.com/llvm/llvm-project/pull/179936

>From 0d402c46c4fe1cb26c45f35d3193c4242a6e068f Mon Sep 17 00:00:00 2001
From: ergawy <kareem.ergawy at amd.com>
Date: Thu, 5 Feb 2026 06:39:34 -0600
Subject: [PATCH 1/3] [flang][OpenMP][DoConcurrent] Emit declare mapper for
 records

Extends `do concurrent` device support by emitting compiler-generated
declare mapper ops for live-ins whose types are record types and have
allocatable members.
---
 flang/include/flang/Utils/OpenMP.h            |   9 ++
 flang/lib/Lower/OpenMP/ClauseProcessor.cpp    |  12 +-
 flang/lib/Lower/OpenMP/OpenMP.cpp             |  15 ++-
 flang/lib/Lower/OpenMP/Utils.cpp              | 107 ------------------
 flang/lib/Lower/OpenMP/Utils.h                |   4 -
 .../OpenMP/DoConcurrentConversion.cpp         |  37 +++++-
 flang/lib/Utils/OpenMP.cpp                    |  97 ++++++++++++++++
 .../DoConcurrent/implicit_mapper.f90          |  28 +++++
 8 files changed, 194 insertions(+), 115 deletions(-)
 create mode 100644 flang/test/Transforms/DoConcurrent/implicit_mapper.f90

diff --git a/flang/include/flang/Utils/OpenMP.h b/flang/include/flang/Utils/OpenMP.h
index bad0abb6f5788..e8627347fd578 100644
--- a/flang/include/flang/Utils/OpenMP.h
+++ b/flang/include/flang/Utils/OpenMP.h
@@ -13,6 +13,7 @@
 
 namespace fir {
 class FirOpBuilder;
+class RecordType;
 } // namespace fir
 
 namespace Fortran::utils::openmp {
@@ -59,6 +60,14 @@ mlir::Value mapTemporaryValue(fir::FirOpBuilder &firOpBuilder,
 /// maps.
 void cloneOrMapRegionOutsiders(
     fir::FirOpBuilder &firOpBuilder, mlir::omp::TargetOp targetOp);
+
+using RecordMemberMapperMangler =
+    std::function<void(std::string &mapperId, llvm::StringRef memberName)>;
+
+mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper(
+    fir::FirOpBuilder &firOpBuilder, mlir::Location loc,
+    fir::RecordType recordType, llvm::StringRef mapperNameStr,
+    RecordMemberMapperMangler mangler = {});
 } // namespace Fortran::utils::openmp
 
 #endif // FORTRAN_UTILS_OPENMP_H_
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 4eed4231646ae..3a2357325b9fd 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1586,8 +1586,16 @@ void ClauseProcessor::processMapObjects(
     if (!recordType)
       return mlir::FlatSymbolRefAttr();
 
-    return getOrGenImplicitDefaultDeclareMapper(converter, clauseLocation,
-                                                recordType, mapperIdName);
+    return utils::openmp::getOrGenImplicitDefaultDeclareMapper(
+        converter.getFirOpBuilder(), clauseLocation, recordType, mapperIdName,
+        [&](std::string &mapperIdName, llvm::StringRef memberName) {
+          if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName))
+            mapperIdName = converter.mangleName(mapperIdName, sym->owner());
+          else if (auto *memberSym =
+                       converter.getCurrentScope().FindSymbol(memberName.str()))
+            mapperIdName =
+                converter.mangleName(mapperIdName, memberSym->owner());
+        });
   };
 
   auto getDefaultMapperID =
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 3375d5db7f9aa..5e63481a5656d 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2857,7 +2857,20 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
                 if (auto recordType = mlir::dyn_cast_or_null<fir::RecordType>(
                         converter.genType(*typeSpec)))
                   mapperId = getOrGenImplicitDefaultDeclareMapper(
-                      converter, loc, recordType, mapperIdName);
+                      converter.getFirOpBuilder(), loc, recordType,
+                      mapperIdName,
+                      [&](std::string &mapperIdName,
+                          llvm::StringRef memberName) {
+                        if (auto *sym = converter.getCurrentScope().FindSymbol(
+                                mapperIdName))
+                          mapperIdName =
+                              converter.mangleName(mapperIdName, sym->owner());
+                        else if (auto *memberSym =
+                                     converter.getCurrentScope().FindSymbol(
+                                         memberName.str()))
+                          mapperIdName = converter.mangleName(
+                              mapperIdName, memberSym->owner());
+                      });
               } else {
                 mapperId = mlir::FlatSymbolRefAttr::get(
                     &converter.getMLIRContext(), mapperIdName);
diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp
index a0fd386e8fecb..12558ffa9f07f 100644
--- a/flang/lib/Lower/OpenMP/Utils.cpp
+++ b/flang/lib/Lower/OpenMP/Utils.cpp
@@ -67,113 +67,6 @@ llvm::cl::opt<bool> treatIndexAsSection(
 namespace Fortran {
 namespace lower {
 namespace omp {
-
-mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper(
-    lower::AbstractConverter &converter, mlir::Location loc,
-    fir::RecordType recordType, llvm::StringRef mapperNameStr) {
-  if (mapperNameStr.empty())
-    return {};
-
-  if (converter.getModuleOp().lookupSymbol(mapperNameStr))
-    return mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(),
-                                        mapperNameStr);
-
-  fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
-  mlir::OpBuilder::InsertionGuard guard(firOpBuilder);
-
-  firOpBuilder.setInsertionPointToStart(converter.getModuleOp().getBody());
-  auto declMapperOp = mlir::omp::DeclareMapperOp::create(
-      firOpBuilder, loc, mapperNameStr, recordType);
-  auto &region = declMapperOp.getRegion();
-  firOpBuilder.createBlock(&region);
-  auto mapperArg = region.addArgument(firOpBuilder.getRefType(recordType), loc);
-
-  auto declareOp = hlfir::DeclareOp::create(firOpBuilder, loc, mapperArg,
-                                            /*uniq_name=*/"");
-
-  const auto genBoundsOps = [&](mlir::Value mapVal,
-                                llvm::SmallVectorImpl<mlir::Value> &bounds) {
-    fir::ExtendedValue extVal =
-        hlfir::translateToExtendedValue(mapVal.getLoc(), firOpBuilder,
-                                        hlfir::Entity{mapVal},
-                                        /*contiguousHint=*/true)
-            .first;
-    fir::factory::AddrAndBoundsInfo info = fir::factory::getDataOperandBaseAddr(
-        firOpBuilder, mapVal, /*isOptional=*/false, mapVal.getLoc());
-    bounds = fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
-                                                mlir::omp::MapBoundsType>(
-        firOpBuilder, info, extVal,
-        /*dataExvIsAssumedSize=*/false, mapVal.getLoc());
-  };
-
-  const auto getFieldRef = [&](mlir::Value rec, llvm::StringRef fieldName,
-                               mlir::Type fieldTy, mlir::Type recType) {
-    mlir::Value field = fir::FieldIndexOp::create(
-        firOpBuilder, loc, fir::FieldType::get(recType.getContext()), fieldName,
-        recType, fir::getTypeParams(rec));
-    return fir::CoordinateOp::create(
-        firOpBuilder, loc, firOpBuilder.getRefType(fieldTy), rec, field);
-  };
-
-  llvm::SmallVector<mlir::Value> clauseMapVars;
-  llvm::SmallVector<llvm::SmallVector<int64_t>> memberPlacementIndices;
-  llvm::SmallVector<mlir::Value> memberMapOps;
-
-  mlir::omp::ClauseMapFlags mapFlag = mlir::omp::ClauseMapFlags::to |
-                                      mlir::omp::ClauseMapFlags::from |
-                                      mlir::omp::ClauseMapFlags::implicit;
-  mlir::omp::VariableCaptureKind captureKind =
-      mlir::omp::VariableCaptureKind::ByRef;
-
-  for (const auto &entry : llvm::enumerate(recordType.getTypeList())) {
-    const auto &memberName = entry.value().first;
-    const auto &memberType = entry.value().second;
-    mlir::FlatSymbolRefAttr mapperId;
-    if (auto recType = mlir::dyn_cast<fir::RecordType>(
-            fir::getFortranElementType(memberType))) {
-      std::string mapperIdName =
-          recType.getName().str() + llvm::omp::OmpDefaultMapperName;
-      if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName))
-        mapperIdName = converter.mangleName(mapperIdName, sym->owner());
-      else if (auto *memberSym =
-                   converter.getCurrentScope().FindSymbol(memberName))
-        mapperIdName = converter.mangleName(mapperIdName, memberSym->owner());
-
-      mapperId = getOrGenImplicitDefaultDeclareMapper(converter, loc, recType,
-                                                      mapperIdName);
-    }
-
-    auto ref =
-        getFieldRef(declareOp.getBase(), memberName, memberType, recordType);
-    llvm::SmallVector<mlir::Value> bounds;
-    genBoundsOps(ref, bounds);
-    mlir::Value mapOp = Fortran::utils::openmp::createMapInfoOp(
-        firOpBuilder, loc, ref, /*varPtrPtr=*/mlir::Value{}, /*name=*/"",
-        bounds,
-        /*members=*/{},
-        /*membersIndex=*/mlir::ArrayAttr{}, mapFlag, captureKind, ref.getType(),
-        /*partialMap=*/false, mapperId);
-    memberMapOps.emplace_back(mapOp);
-    memberPlacementIndices.emplace_back(
-        llvm::SmallVector<int64_t>{(int64_t)entry.index()});
-  }
-
-  llvm::SmallVector<mlir::Value> bounds;
-  genBoundsOps(declareOp.getOriginalBase(), bounds);
-  mlir::omp::ClauseMapFlags parentMapFlag = mlir::omp::ClauseMapFlags::implicit;
-  mlir::omp::MapInfoOp mapOp = Fortran::utils::openmp::createMapInfoOp(
-      firOpBuilder, loc, declareOp.getOriginalBase(),
-      /*varPtrPtr=*/mlir::Value(), /*name=*/"", bounds, memberMapOps,
-      firOpBuilder.create2DI64ArrayAttr(memberPlacementIndices), parentMapFlag,
-      captureKind, declareOp.getType(0),
-      /*partialMap=*/true);
-
-  clauseMapVars.emplace_back(mapOp);
-  mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseMapVars);
-  return mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(),
-                                      mapperNameStr);
-}
-
 bool requiresImplicitDefaultDeclareMapper(
     const semantics::DerivedTypeSpec &typeSpec) {
   // ISO C interoperable types (e.g., c_ptr, c_funptr) must always have implicit
diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h
index 44381da853ecb..7c9a1f8aa07b0 100644
--- a/flang/lib/Lower/OpenMP/Utils.h
+++ b/flang/lib/Lower/OpenMP/Utils.h
@@ -139,10 +139,6 @@ mlir::Value createParentSymAndGenIntermediateMaps(
     OmpMapParentAndMemberData &parentMemberIndices, llvm::StringRef asFortran,
     mlir::omp::ClauseMapFlags mapTypeBits);
 
-mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper(
-    Fortran::lower::AbstractConverter &converter, mlir::Location loc,
-    fir::RecordType recordType, llvm::StringRef mapperNameStr);
-
 bool requiresImplicitDefaultDeclareMapper(
     const semantics::DerivedTypeSpec &typeSpec);
 
diff --git a/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp b/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp
index ff346e79276ce..ce36596602909 100644
--- a/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp
+++ b/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp
@@ -22,6 +22,7 @@
 #include "mlir/Transforms/DialectConversion.h"
 #include "mlir/Transforms/RegionUtils.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Frontend/OpenMP/OMPConstants.h"
 
 namespace flangomp {
 #define GEN_PASS_DEF_DOCONCURRENTCONVERSIONPASS
@@ -583,12 +584,46 @@ class DoConcurrentConversion
     llvm::SmallVector<mlir::Value> boundsOps;
     genBoundsOps(builder, liveIn, rawAddr, boundsOps);
 
+    auto asRecordType = [&](mlir::Type eleType) {
+      fir::RecordType recordType = mlir::dyn_cast<fir::RecordType>(eleType);
+
+      if (auto seqType = mlir::dyn_cast<fir::SequenceType>(eleType))
+        recordType = mlir::dyn_cast<fir::RecordType>(seqType.getElementType());
+
+      return recordType;
+    };
+
+    fir::RecordType recordType = asRecordType(eleType);
+
+    bool requiresImplcitMapper = [&]() {
+      if (!recordType)
+        return false;
+
+      for (auto [fieldName, fieldType] : recordType.getTypeList()) {
+        if (fir::isAllocatableType(fieldType))
+          return true;
+
+        if (asRecordType(fieldType))
+          TODO(liveIn.getLoc(), "Nested record types are not supported yet.");
+      }
+
+      return false;
+    }();
+
+    mlir::FlatSymbolRefAttr mapperId;
+    if (requiresImplcitMapper) {
+      std::string mapperIdName =
+          recordType.getName().str() + llvm::omp::OmpDefaultMapperName;
+      mapperId = Fortran::utils::openmp::getOrGenImplicitDefaultDeclareMapper(
+          builder, liveIn.getLoc(), recordType, mapperIdName);
+    }
+
     return Fortran::utils::openmp::createMapInfoOp(
         builder, liveIn.getLoc(), rawAddr,
         /*varPtrPtr=*/{}, name.str(), boundsOps,
         /*members=*/{},
         /*membersIndex=*/mlir::ArrayAttr{}, mapFlag, captureKind,
-        rawAddr.getType());
+        rawAddr.getType(), /*partialMap=*/false, mapperId);
   }
 
   mlir::omp::TargetOp
diff --git a/flang/lib/Utils/OpenMP.cpp b/flang/lib/Utils/OpenMP.cpp
index c2036c4a383fd..a0a67249f7f05 100644
--- a/flang/lib/Utils/OpenMP.cpp
+++ b/flang/lib/Utils/OpenMP.cpp
@@ -155,4 +155,101 @@ void cloneOrMapRegionOutsiders(
     mlir::getUsedValuesDefinedAbove(region, valuesDefinedAbove);
   }
 }
+
+mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper(
+    fir::FirOpBuilder &firOpBuilder, mlir::Location loc,
+    fir::RecordType recordType, llvm::StringRef mapperNameStr,
+    RecordMemberMapperMangler mangler) {
+  if (mapperNameStr.empty())
+    return {};
+
+  mlir::ModuleOp moduleOp = firOpBuilder.getModule();
+  if (moduleOp.lookupSymbol(mapperNameStr))
+    return mlir::FlatSymbolRefAttr::get(
+        firOpBuilder.getContext(), mapperNameStr);
+
+  mlir::OpBuilder::InsertionGuard guard(firOpBuilder);
+
+  firOpBuilder.setInsertionPointToStart(moduleOp.getBody());
+  auto declMapperOp = mlir::omp::DeclareMapperOp::create(
+      firOpBuilder, loc, mapperNameStr, recordType);
+  auto &region = declMapperOp.getRegion();
+  firOpBuilder.createBlock(&region);
+  auto mapperArg = region.addArgument(firOpBuilder.getRefType(recordType), loc);
+
+  auto declareOp = hlfir::DeclareOp::create(firOpBuilder, loc, mapperArg,
+      /*uniq_name=*/"");
+
+  const auto genBoundsOps = [&](mlir::Value mapVal,
+                                llvm::SmallVectorImpl<mlir::Value> &bounds) {
+    fir::ExtendedValue extVal = hlfir::translateToExtendedValue(mapVal.getLoc(),
+        firOpBuilder, hlfir::Entity{mapVal},
+        /*contiguousHint=*/true)
+                                    .first;
+    fir::factory::AddrAndBoundsInfo info = fir::factory::getDataOperandBaseAddr(
+        firOpBuilder, mapVal, /*isOptional=*/false, mapVal.getLoc());
+    bounds = fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
+        mlir::omp::MapBoundsType>(firOpBuilder, info, extVal,
+        /*dataExvIsAssumedSize=*/false, mapVal.getLoc());
+  };
+
+  const auto getFieldRef = [&](mlir::Value rec, llvm::StringRef fieldName,
+                               mlir::Type fieldTy, mlir::Type recType) {
+    mlir::Value field = fir::FieldIndexOp::create(firOpBuilder, loc,
+        fir::FieldType::get(recType.getContext()), fieldName, recType,
+        fir::getTypeParams(rec));
+    return fir::CoordinateOp::create(
+        firOpBuilder, loc, firOpBuilder.getRefType(fieldTy), rec, field);
+  };
+
+  llvm::SmallVector<mlir::Value> clauseMapVars;
+  llvm::SmallVector<llvm::SmallVector<int64_t>> memberPlacementIndices;
+  llvm::SmallVector<mlir::Value> memberMapOps;
+
+  mlir::omp::ClauseMapFlags mapFlag = mlir::omp::ClauseMapFlags::to |
+      mlir::omp::ClauseMapFlags::from | mlir::omp::ClauseMapFlags::implicit;
+  mlir::omp::VariableCaptureKind captureKind =
+      mlir::omp::VariableCaptureKind::ByRef;
+
+  for (const auto &entry : llvm::enumerate(recordType.getTypeList())) {
+    const auto &memberName = entry.value().first;
+    const auto &memberType = entry.value().second;
+    mlir::FlatSymbolRefAttr mapperId;
+    if (auto recType = mlir::dyn_cast<fir::RecordType>(
+            fir::getFortranElementType(memberType))) {
+      std::string mapperIdName =
+          recType.getName().str() + llvm::omp::OmpDefaultMapperName;
+      mangler(mapperIdName, memberName);
+      mapperId = getOrGenImplicitDefaultDeclareMapper(
+          firOpBuilder, loc, recType, mapperIdName, mangler);
+    }
+
+    auto ref =
+        getFieldRef(declareOp.getBase(), memberName, memberType, recordType);
+    llvm::SmallVector<mlir::Value> bounds;
+    genBoundsOps(ref, bounds);
+    mlir::Value mapOp = Fortran::utils::openmp::createMapInfoOp(firOpBuilder,
+        loc, ref, /*varPtrPtr=*/mlir::Value{}, /*name=*/"", bounds,
+        /*members=*/{},
+        /*membersIndex=*/mlir::ArrayAttr{}, mapFlag, captureKind, ref.getType(),
+        /*partialMap=*/false, mapperId);
+    memberMapOps.emplace_back(mapOp);
+    memberPlacementIndices.emplace_back(
+        llvm::SmallVector<int64_t>{(int64_t)entry.index()});
+  }
+
+  llvm::SmallVector<mlir::Value> bounds;
+  genBoundsOps(declareOp.getOriginalBase(), bounds);
+  mlir::omp::ClauseMapFlags parentMapFlag = mlir::omp::ClauseMapFlags::implicit;
+  mlir::omp::MapInfoOp mapOp = Fortran::utils::openmp::createMapInfoOp(
+      firOpBuilder, loc, declareOp.getOriginalBase(),
+      /*varPtrPtr=*/mlir::Value(), /*name=*/"", bounds, memberMapOps,
+      firOpBuilder.create2DI64ArrayAttr(memberPlacementIndices), parentMapFlag,
+      captureKind, declareOp.getType(0),
+      /*partialMap=*/true);
+
+  clauseMapVars.emplace_back(mapOp);
+  mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseMapVars);
+  return mlir::FlatSymbolRefAttr::get(firOpBuilder.getContext(), mapperNameStr);
+}
 } // namespace Fortran::utils::openmp
diff --git a/flang/test/Transforms/DoConcurrent/implicit_mapper.f90 b/flang/test/Transforms/DoConcurrent/implicit_mapper.f90
new file mode 100644
index 0000000000000..f77c0cd0320cd
--- /dev/null
+++ b/flang/test/Transforms/DoConcurrent/implicit_mapper.f90
@@ -0,0 +1,28 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fdo-concurrent-to-openmp=device %s -o - \
+! RUN:   | FileCheck %s
+
+module record_with_alloc_mod
+  implicit none
+  public :: record_with_alloc
+
+  type record_with_alloc
+    real, allocatable :: values_(:)
+  end type
+end module record_with_alloc_mod
+
+subroutine random_inputs()
+  use record_with_alloc_mod, only : record_with_alloc
+  implicit none
+  type(record_with_alloc) :: inputs(2)
+  integer :: i
+
+  do concurrent(i=1:10)
+    inputs(1)%values_ = [1,2,3,4]
+  end do
+end subroutine
+
+! CHECK: omp.declare_mapper @[[MAPPER_NAME:.*record_with_alloc_omp_default_mapper]] : !fir.type<{{.*}}record_with_alloc{{.*}}>
+
+! CHECK: func.func @{{.*}}random_inputs()
+! CHECK:   %[[ARR_DECL:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "{{.*}}inputs"}
+! CHECK:   omp.map.info var_ptr(%[[ARR_DECL]]#1 : {{.*}}) {{.*}} mapper(@[[MAPPER_NAME]])

>From 487a49893e13b20a6250576afbe808a14f95a995 Mon Sep 17 00:00:00 2001
From: ergawy <kareem.ergawy at amd.com>
Date: Mon, 9 Mar 2026 07:34:57 -0500
Subject: [PATCH 2/3] Use FIR utils

---
 flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp b/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp
index ce36596602909..e9f7323c915ac 100644
--- a/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp
+++ b/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp
@@ -585,12 +585,8 @@ class DoConcurrentConversion
     genBoundsOps(builder, liveIn, rawAddr, boundsOps);
 
     auto asRecordType = [&](mlir::Type eleType) {
-      fir::RecordType recordType = mlir::dyn_cast<fir::RecordType>(eleType);
-
-      if (auto seqType = mlir::dyn_cast<fir::SequenceType>(eleType))
-        recordType = mlir::dyn_cast<fir::RecordType>(seqType.getElementType());
-
-      return recordType;
+      return mlir::dyn_cast<fir::RecordType>(
+          fir::getDerivedType(fir::unwrapRefType(eleType)));
     };
 
     fir::RecordType recordType = asRecordType(eleType);

>From 8ef5ff6961b3fd18d300328b230159441b7913c6 Mon Sep 17 00:00:00 2001
From: ergawy <kareem.ergawy at amd.com>
Date: Mon, 9 Mar 2026 10:14:40 -0500
Subject: [PATCH 3/3] Review comments

---
 flang/lib/Lower/OpenMP/ClauseProcessor.cpp            |  7 +------
 flang/lib/Lower/OpenMP/OpenMP.cpp                     | 10 +---------
 flang/lib/Lower/OpenMP/Utils.cpp                      |  9 +++++++++
 flang/lib/Lower/OpenMP/Utils.h                        |  8 ++++++++
 flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp |  1 +
 flang/lib/Utils/OpenMP.cpp                            |  7 +++++++
 6 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 3a2357325b9fd..5e8683024e6eb 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1589,12 +1589,7 @@ void ClauseProcessor::processMapObjects(
     return utils::openmp::getOrGenImplicitDefaultDeclareMapper(
         converter.getFirOpBuilder(), clauseLocation, recordType, mapperIdName,
         [&](std::string &mapperIdName, llvm::StringRef memberName) {
-          if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName))
-            mapperIdName = converter.mangleName(mapperIdName, sym->owner());
-          else if (auto *memberSym =
-                       converter.getCurrentScope().FindSymbol(memberName.str()))
-            mapperIdName =
-                converter.mangleName(mapperIdName, memberSym->owner());
+          defaultMangler(converter, mapperIdName, memberName);
         });
   };
 
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 5e63481a5656d..e2328b39c180f 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2861,15 +2861,7 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
                       mapperIdName,
                       [&](std::string &mapperIdName,
                           llvm::StringRef memberName) {
-                        if (auto *sym = converter.getCurrentScope().FindSymbol(
-                                mapperIdName))
-                          mapperIdName =
-                              converter.mangleName(mapperIdName, sym->owner());
-                        else if (auto *memberSym =
-                                     converter.getCurrentScope().FindSymbol(
-                                         memberName.str()))
-                          mapperIdName = converter.mangleName(
-                              mapperIdName, memberSym->owner());
+                        defaultMangler(converter, mapperIdName, memberName);
                       });
               } else {
                 mapperId = mlir::FlatSymbolRefAttr::get(
diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp
index 12558ffa9f07f..b7d1cb8b419fd 100644
--- a/flang/lib/Lower/OpenMP/Utils.cpp
+++ b/flang/lib/Lower/OpenMP/Utils.cpp
@@ -995,6 +995,15 @@ bool hasIteratorIVReference(
   return false;
 }
 
+void defaultMangler(Fortran::lower::AbstractConverter &converter,
+                    std::string &mapperIdName, llvm::StringRef memberName) {
+  if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName))
+    mapperIdName = converter.mangleName(mapperIdName, sym->owner());
+  else if (auto *memberSym =
+               converter.getCurrentScope().FindSymbol(memberName.str()))
+    mapperIdName = converter.mangleName(mapperIdName, memberSym->owner());
+}
+
 // Build the array coordinate for an object that uses iterator variables.
 // If the object is a section, use the first element of that section
 // as the coordinate. Currently only support top-level ArrayRef designators.
diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h
index 7c9a1f8aa07b0..587a078c33ed8 100644
--- a/flang/lib/Lower/OpenMP/Utils.h
+++ b/flang/lib/Lower/OpenMP/Utils.h
@@ -212,6 +212,14 @@ bool hasIteratorIVReference(
     const omp::Object &object,
     const llvm::SmallPtrSetImpl<const Fortran::semantics::Symbol *> &ivSyms);
 
+/// Default name mangler for implicit default mappers.
+///
+/// \param converter The converter to use for name mangling.
+/// \param mapperIdName The name of the mapper to mangle.
+/// \param memberName The name of the member to mangle.
+void defaultMangler(Fortran::lower::AbstractConverter &converter,
+                    std::string &mapperIdName, llvm::StringRef memberName);
+
 mlir::Value genIteratorCoordinate(Fortran::lower::AbstractConverter &converter,
                                   hlfir::Entity entity,
                                   llvm::ArrayRef<mlir::Value> ivs,
diff --git a/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp b/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp
index e9f7323c915ac..876a54d29837e 100644
--- a/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp
+++ b/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp
@@ -610,6 +610,7 @@ class DoConcurrentConversion
     if (requiresImplcitMapper) {
       std::string mapperIdName =
           recordType.getName().str() + llvm::omp::OmpDefaultMapperName;
+      // TODO Add a mangler callback once nested record types are supported.
       mapperId = Fortran::utils::openmp::getOrGenImplicitDefaultDeclareMapper(
           builder, liveIn.getLoc(), recordType, mapperIdName);
     }
diff --git a/flang/lib/Utils/OpenMP.cpp b/flang/lib/Utils/OpenMP.cpp
index a0a67249f7f05..cd6b7f310dd75 100644
--- a/flang/lib/Utils/OpenMP.cpp
+++ b/flang/lib/Utils/OpenMP.cpp
@@ -156,6 +156,13 @@ void cloneOrMapRegionOutsiders(
   }
 }
 
+/// Gets or generates a default declare mapper for a given record type.
+///
+/// \param firOpBuilder The builder to use for generating the mapper.
+/// \param loc The location to use for the generated operations.
+/// \param recordType The record type to generate the mapper for.
+/// \param mapperNameStr The name of the mapper to generate.
+/// \param mangler A function to mangle the mapper name for nested types.
 mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper(
     fir::FirOpBuilder &firOpBuilder, mlir::Location loc,
     fir::RecordType recordType, llvm::StringRef mapperNameStr,



More information about the flang-commits mailing list