[flang-commits] [flang] [acc][flang] lowering of acc declare on COMMON variables (PR #163676)

Susan Tan ス-ザン タン via flang-commits flang-commits at lists.llvm.org
Fri Oct 17 15:42:23 PDT 2025


https://github.com/SusanTan updated https://github.com/llvm/llvm-project/pull/163676

>From 3582fd5f7b4588bae0100f068a56c32ad92a790b Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Wed, 15 Oct 2025 15:36:14 -0700
Subject: [PATCH 01/12] initial implementation

---
 flang/lib/Lower/OpenACC.cpp | 274 +++++++++++++++++++++++++++++++++++-
 1 file changed, 268 insertions(+), 6 deletions(-)

diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index cfb18914e8126..9e940743bd377 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -4112,12 +4112,26 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
     DeclareOp::create(builder, loc, mlir::Value{},
                       mlir::ValueRange(entryOp.getAccVar()));
   if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalDestructorOp>) {
-    ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
-                   entryOp.getBounds(), entryOp.getAsyncOperands(),
-                   entryOp.getAsyncOperandsDeviceTypeAttr(),
-                   entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
-                   /*structured=*/false, /*implicit=*/false,
-                   builder.getStringAttr(*entryOp.getName()));
+    if constexpr (std::is_same_v<ExitOp, mlir::acc::DeclareLinkOp>) {
+      // No destructor emission for declare link in this path to avoid
+      // complex var/varType/varPtrPtr signatures. The ctor registers the link.
+    } else if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
+                         std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>) {
+      ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
+                     entryOp.getVar(), entryOp.getVarType(),
+                     entryOp.getBounds(), entryOp.getAsyncOperands(),
+                     entryOp.getAsyncOperandsDeviceTypeAttr(),
+                     entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
+                     /*structured=*/false, /*implicit=*/false,
+                     builder.getStringAttr(*entryOp.getName()));
+    } else {
+      ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
+                     entryOp.getBounds(), entryOp.getAsyncOperands(),
+                     entryOp.getAsyncOperandsDeviceTypeAttr(),
+                     entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
+                     /*structured=*/false, /*implicit=*/false,
+                     builder.getStringAttr(*entryOp.getName()));
+    }
   }
   mlir::acc::TerminatorOp::create(builder, loc);
   modBuilder.setInsertionPointAfter(declareGlobalOp);
@@ -4329,6 +4343,58 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
           createClause->v;
       const auto &accObjectList =
           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+      // Emit module-level declare for COMMON symbols in this clause.
+      for (const auto &obj : accObjectList.v) {
+        Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+        if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+            Fortran::semantics::FindCommonBlockContaining(sym)) {
+          std::string globalName = converter.mangleName(sym);
+          fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+          if (!globalOp) {
+            if (Fortran::semantics::FindEquivalenceSet(sym)) {
+              for (Fortran::semantics::EquivalenceObject eqObj :
+                   *Fortran::semantics::FindEquivalenceSet(sym)) {
+                std::string eqName = converter.mangleName(eqObj.symbol);
+                globalOp = builder.getNamedGlobal(eqName);
+                if (globalOp)
+                  break;
+              }
+            }
+          }
+          if (!globalOp)
+            llvm::report_fatal_error("could not retrieve global symbol");
+          std::stringstream ctorName;
+          ctorName << globalName << "_acc_ctor";
+          if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+                  ctorName.str())) {
+            mlir::Location operandLocation = genOperandLocation(converter, obj);
+            addDeclareAttr(builder, globalOp.getOperation(),
+                mlir::acc::DataClause::acc_create);
+            mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+            modBuilder.setInsertionPointAfter(globalOp);
+            std::stringstream asFortran;
+            asFortran << sym.name().ToString();
+            auto savedIP = builder.saveInsertionPoint();
+            createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+                                  mlir::acc::CreateOp,
+                                  mlir::acc::DeclareEnterOp,
+                                  mlir::acc::DeleteOp>(modBuilder, builder,
+                    operandLocation, globalOp,
+                    mlir::acc::DataClause::acc_create, ctorName.str(),
+                    /*implicit=*/false, asFortran);
+            std::stringstream dtorName;
+            dtorName << globalName << "_acc_dtor";
+            createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+                                  mlir::acc::GetDevicePtrOp,
+                                  mlir::acc::DeclareExitOp,
+                                  mlir::acc::DeleteOp>(modBuilder, builder,
+                    operandLocation, globalOp,
+                    mlir::acc::DataClause::acc_create, dtorName.str(),
+                    /*implicit=*/false, asFortran);
+            builder.restoreInsertionPoint(savedIP);
+          }
+        }
+      }
       auto crtDataStart = dataClauseOperands.size();
       genDeclareDataOperandOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
           accObjectList, converter, semanticsContext, stmtCtx,
@@ -4349,6 +4415,61 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
                                   dataClauseOperands.end());
     } else if (const auto *copyinClause =
                    std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
+      // Emit module-level declare for COMMON symbols in this clause.
+      const auto &listWithModifier = copyinClause->v;
+      const auto &copyinObjs =
+          std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+      for (const auto &obj : copyinObjs.v) {
+        Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+        if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+            Fortran::semantics::FindCommonBlockContaining(sym)) {
+          std::string globalName = converter.mangleName(sym);
+          fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+          if (!globalOp) {
+            if (Fortran::semantics::FindEquivalenceSet(sym)) {
+              for (Fortran::semantics::EquivalenceObject eqObj :
+                   *Fortran::semantics::FindEquivalenceSet(sym)) {
+                std::string eqName = converter.mangleName(eqObj.symbol);
+                globalOp = builder.getNamedGlobal(eqName);
+                if (globalOp)
+                  break;
+              }
+            }
+          }
+          if (!globalOp)
+            llvm::report_fatal_error("could not retrieve global symbol");
+          std::stringstream ctorName;
+          ctorName << globalName << "_acc_ctor";
+          if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+                  ctorName.str())) {
+            mlir::Location operandLocation = genOperandLocation(converter, obj);
+            addDeclareAttr(builder, globalOp.getOperation(),
+                mlir::acc::DataClause::acc_copyin);
+            mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+            modBuilder.setInsertionPointAfter(globalOp);
+            std::stringstream asFortran;
+            asFortran << sym.name().ToString();
+            auto savedIP = builder.saveInsertionPoint();
+            createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+                                  mlir::acc::CopyinOp,
+                                  mlir::acc::DeclareEnterOp,
+                                  mlir::acc::DeleteOp>(modBuilder, builder,
+                    operandLocation, globalOp,
+                    mlir::acc::DataClause::acc_copyin, ctorName.str(),
+                    /*implicit=*/false, asFortran);
+            std::stringstream dtorName;
+            dtorName << globalName << "_acc_dtor";
+            createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+                                  mlir::acc::GetDevicePtrOp,
+                                  mlir::acc::DeclareExitOp,
+                                  mlir::acc::DeleteOp>(modBuilder, builder,
+                    operandLocation, globalOp,
+                    mlir::acc::DataClause::acc_copyin, dtorName.str(),
+                    /*implicit=*/false, asFortran);
+            builder.restoreInsertionPoint(savedIP);
+          }
+        }
+      }
       auto crtDataStart = dataClauseOperands.size();
       genDeclareDataOperandOperationsWithModifier<mlir::acc::CopyinOp,
                                                   mlir::acc::DeleteOp>(
@@ -4365,6 +4486,58 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
           copyoutClause->v;
       const auto &accObjectList =
           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+      // Emit module-level declare for COMMON symbols in this clause.
+      for (const auto &obj : accObjectList.v) {
+        Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+        if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+            Fortran::semantics::FindCommonBlockContaining(sym)) {
+          std::string globalName = converter.mangleName(sym);
+          fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+          if (!globalOp) {
+            if (Fortran::semantics::FindEquivalenceSet(sym)) {
+              for (Fortran::semantics::EquivalenceObject eqObj :
+                   *Fortran::semantics::FindEquivalenceSet(sym)) {
+                std::string eqName = converter.mangleName(eqObj.symbol);
+                globalOp = builder.getNamedGlobal(eqName);
+                if (globalOp)
+                  break;
+              }
+            }
+          }
+          if (!globalOp)
+            llvm::report_fatal_error("could not retrieve global symbol");
+          std::stringstream ctorName;
+          ctorName << globalName << "_acc_ctor";
+          if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+                  ctorName.str())) {
+            mlir::Location operandLocation = genOperandLocation(converter, obj);
+            addDeclareAttr(builder, globalOp.getOperation(),
+                mlir::acc::DataClause::acc_copyout);
+            mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+            modBuilder.setInsertionPointAfter(globalOp);
+            std::stringstream asFortran;
+            asFortran << sym.name().ToString();
+            auto savedIP = builder.saveInsertionPoint();
+            createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+                                  mlir::acc::CreateOp,
+                                  mlir::acc::DeclareEnterOp,
+                                  mlir::acc::CopyoutOp>(modBuilder, builder,
+                    operandLocation, globalOp,
+                    mlir::acc::DataClause::acc_copyout, ctorName.str(),
+                    /*implicit=*/false, asFortran);
+            std::stringstream dtorName;
+            dtorName << globalName << "_acc_dtor";
+            createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+                                  mlir::acc::GetDevicePtrOp,
+                                  mlir::acc::DeclareExitOp,
+                                  mlir::acc::CopyoutOp>(modBuilder, builder,
+                    operandLocation, globalOp,
+                    mlir::acc::DataClause::acc_copyout, dtorName.str(),
+                    /*implicit=*/false, asFortran);
+            builder.restoreInsertionPoint(savedIP);
+          }
+        }
+      }
       auto crtDataStart = dataClauseOperands.size();
       genDeclareDataOperandOperations<mlir::acc::CreateOp,
                                       mlir::acc::CopyoutOp>(
@@ -4383,6 +4556,50 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
           /*structured=*/true, /*implicit=*/false);
     } else if (const auto *linkClause =
                    std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
+      // Emit module-level declare for COMMON symbols in this clause.
+      const auto &linkObjs = linkClause->v;
+      for (const auto &obj : linkObjs.v) {
+        Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+        if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+            Fortran::semantics::FindCommonBlockContaining(sym)) {
+          std::string globalName = converter.mangleName(sym);
+          fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+          if (!globalOp) {
+            if (Fortran::semantics::FindEquivalenceSet(sym)) {
+              for (Fortran::semantics::EquivalenceObject eqObj :
+                   *Fortran::semantics::FindEquivalenceSet(sym)) {
+                std::string eqName = converter.mangleName(eqObj.symbol);
+                globalOp = builder.getNamedGlobal(eqName);
+                if (globalOp)
+                  break;
+              }
+            }
+          }
+          if (!globalOp)
+            llvm::report_fatal_error("could not retrieve global symbol");
+          std::stringstream ctorName;
+          ctorName << globalName << "_acc_ctor";
+          if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+                  ctorName.str())) {
+            mlir::Location operandLocation = genOperandLocation(converter, obj);
+            addDeclareAttr(builder, globalOp.getOperation(),
+                mlir::acc::DataClause::acc_declare_link);
+            mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+            modBuilder.setInsertionPointAfter(globalOp);
+            std::stringstream asFortran;
+            asFortran << sym.name().ToString();
+            auto savedIP = builder.saveInsertionPoint();
+            createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+                                  mlir::acc::DeclareLinkOp,
+                                  mlir::acc::DeclareEnterOp,
+                                  mlir::acc::DeclareLinkOp>(modBuilder, builder,
+                    operandLocation, globalOp,
+                    mlir::acc::DataClause::acc_declare_link, ctorName.str(),
+                    /*implicit=*/false, asFortran);
+            builder.restoreInsertionPoint(savedIP);
+          }
+        }
+      }
       genDeclareDataOperandOperations<mlir::acc::DeclareLinkOp,
                                       mlir::acc::DeclareLinkOp>(
           linkClause->v, converter, semanticsContext, stmtCtx,
@@ -4391,6 +4608,51 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
     } else if (const auto *deviceResidentClause =
                    std::get_if<Fortran::parser::AccClause::DeviceResident>(
                        &clause.u)) {
+      // Emit module-level declare for COMMON symbols in this clause.
+      const auto &devResObjs = deviceResidentClause->v;
+      for (const auto &obj : devResObjs.v) {
+        Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+        if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+            Fortran::semantics::FindCommonBlockContaining(sym)) {
+          std::string globalName = converter.mangleName(sym);
+          fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+          if (!globalOp) {
+            if (Fortran::semantics::FindEquivalenceSet(sym)) {
+              for (Fortran::semantics::EquivalenceObject eqObj :
+                   *Fortran::semantics::FindEquivalenceSet(sym)) {
+                std::string eqName = converter.mangleName(eqObj.symbol);
+                globalOp = builder.getNamedGlobal(eqName);
+                if (globalOp)
+                  break;
+              }
+            }
+          }
+          if (!globalOp)
+            llvm::report_fatal_error("could not retrieve global symbol");
+          std::stringstream ctorName;
+          ctorName << globalName << "_acc_ctor";
+          if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+                  ctorName.str())) {
+            mlir::Location operandLocation = genOperandLocation(converter, obj);
+            addDeclareAttr(builder, globalOp.getOperation(),
+                mlir::acc::DataClause::acc_declare_device_resident);
+            mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+            modBuilder.setInsertionPointAfter(globalOp);
+            std::stringstream asFortran;
+            asFortran << sym.name().ToString();
+            auto savedIP = builder.saveInsertionPoint();
+            createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+                                  mlir::acc::DeclareDeviceResidentOp,
+                                  mlir::acc::DeclareEnterOp,
+                                  mlir::acc::DeleteOp>(modBuilder, builder,
+                    operandLocation, globalOp,
+                    mlir::acc::DataClause::acc_declare_device_resident,
+                    ctorName.str(),
+                    /*implicit=*/false, asFortran);
+            builder.restoreInsertionPoint(savedIP);
+          }
+        }
+      }
       auto crtDataStart = dataClauseOperands.size();
       genDeclareDataOperandOperations<mlir::acc::DeclareDeviceResidentOp,
                                       mlir::acc::DeleteOp>(

>From c6ee3b92db518a4e121203556e17b06fb5516825 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Wed, 15 Oct 2025 15:56:11 -0700
Subject: [PATCH 02/12] refactor

---
 flang/lib/Lower/OpenACC.cpp | 342 ++++++++++++------------------------
 1 file changed, 117 insertions(+), 225 deletions(-)

diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 9e940743bd377..37abcffc683d9 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -3398,6 +3398,7 @@ genACCHostDataOp(Fortran::lower::AbstractConverter &converter,
 
   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
 
+
   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
     mlir::Location clauseLocation = converter.genLocation(clause.source);
     if (const auto *ifClause =
@@ -4326,6 +4327,50 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
   Fortran::lower::StatementContext stmtCtx;
   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
 
+  // Inline helper to emit module-level declare for COMMON symbols in a clause.
+  auto emitCommonGlobal = [&](const Fortran::parser::AccObject &obj,
+                              mlir::acc::DataClause clause,
+                              auto emitCtorDtor) {
+    Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+    if (!(sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+          Fortran::semantics::FindCommonBlockContaining(sym)))
+      return;
+
+    std::string globalName = converter.mangleName(sym);
+    fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+    if (!globalOp) {
+      if (Fortran::semantics::FindEquivalenceSet(sym)) {
+        for (Fortran::semantics::EquivalenceObject eqObj :
+             *Fortran::semantics::FindEquivalenceSet(sym)) {
+          std::string eqName = converter.mangleName(eqObj.symbol);
+          globalOp = builder.getNamedGlobal(eqName);
+          if (globalOp)
+            break;
+        }
+      }
+    }
+    if (!globalOp)
+      llvm::report_fatal_error("could not retrieve global symbol");
+
+    std::stringstream ctorName;
+    ctorName << globalName << "_acc_ctor";
+    if (builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+            ctorName.str()))
+      return;
+
+    mlir::Location operandLocation = genOperandLocation(converter, obj);
+    addDeclareAttr(builder, globalOp.getOperation(), clause);
+    mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+    modBuilder.setInsertionPointAfter(globalOp);
+    std::stringstream asFortran;
+    asFortran << sym.name().ToString();
+
+    auto savedIP = builder.saveInsertionPoint();
+    emitCtorDtor(modBuilder, operandLocation, globalOp, clause, asFortran,
+                 ctorName.str());
+    builder.restoreInsertionPoint(savedIP);
+  };
+
   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
     if (const auto *copyClause =
             std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
@@ -4343,57 +4388,26 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
           createClause->v;
       const auto &accObjectList =
           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
-      // Emit module-level declare for COMMON symbols in this clause.
       for (const auto &obj : accObjectList.v) {
-        Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
-        if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
-            Fortran::semantics::FindCommonBlockContaining(sym)) {
-          std::string globalName = converter.mangleName(sym);
-          fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
-          if (!globalOp) {
-            if (Fortran::semantics::FindEquivalenceSet(sym)) {
-              for (Fortran::semantics::EquivalenceObject eqObj :
-                   *Fortran::semantics::FindEquivalenceSet(sym)) {
-                std::string eqName = converter.mangleName(eqObj.symbol);
-                globalOp = builder.getNamedGlobal(eqName);
-                if (globalOp)
-                  break;
-              }
-            }
-          }
-          if (!globalOp)
-            llvm::report_fatal_error("could not retrieve global symbol");
-          std::stringstream ctorName;
-          ctorName << globalName << "_acc_ctor";
-          if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
-                  ctorName.str())) {
-            mlir::Location operandLocation = genOperandLocation(converter, obj);
-            addDeclareAttr(builder, globalOp.getOperation(),
-                mlir::acc::DataClause::acc_create);
-            mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
-            modBuilder.setInsertionPointAfter(globalOp);
-            std::stringstream asFortran;
-            asFortran << sym.name().ToString();
-            auto savedIP = builder.saveInsertionPoint();
-            createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
-                                  mlir::acc::CreateOp,
-                                  mlir::acc::DeclareEnterOp,
-                                  mlir::acc::DeleteOp>(modBuilder, builder,
-                    operandLocation, globalOp,
-                    mlir::acc::DataClause::acc_create, ctorName.str(),
+        emitCommonGlobal(obj, mlir::acc::DataClause::acc_create,
+            [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
+                fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+                std::stringstream &asFortran, const std::string &ctorName) {
+              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+                                    mlir::acc::CreateOp,
+                                    mlir::acc::DeclareEnterOp,
+                                    mlir::acc::DeleteOp>(modBuilder, builder,
+                    operandLocation, globalOp, clause, ctorName,
                     /*implicit=*/false, asFortran);
-            std::stringstream dtorName;
-            dtorName << globalName << "_acc_dtor";
-            createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
-                                  mlir::acc::GetDevicePtrOp,
-                                  mlir::acc::DeclareExitOp,
-                                  mlir::acc::DeleteOp>(modBuilder, builder,
-                    operandLocation, globalOp,
-                    mlir::acc::DataClause::acc_create, dtorName.str(),
+              std::stringstream dtorName;
+              dtorName << globalOp.getSymName().str() << "_acc_dtor";
+              createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+                                    mlir::acc::GetDevicePtrOp,
+                                    mlir::acc::DeclareExitOp,
+                                    mlir::acc::DeleteOp>(modBuilder, builder,
+                    operandLocation, globalOp, clause, dtorName.str(),
                     /*implicit=*/false, asFortran);
-            builder.restoreInsertionPoint(savedIP);
-          }
-        }
+            });
       }
       auto crtDataStart = dataClauseOperands.size();
       genDeclareDataOperandOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
@@ -4415,60 +4429,29 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
                                   dataClauseOperands.end());
     } else if (const auto *copyinClause =
                    std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
-      // Emit module-level declare for COMMON symbols in this clause.
       const auto &listWithModifier = copyinClause->v;
       const auto &copyinObjs =
           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
       for (const auto &obj : copyinObjs.v) {
-        Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
-        if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
-            Fortran::semantics::FindCommonBlockContaining(sym)) {
-          std::string globalName = converter.mangleName(sym);
-          fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
-          if (!globalOp) {
-            if (Fortran::semantics::FindEquivalenceSet(sym)) {
-              for (Fortran::semantics::EquivalenceObject eqObj :
-                   *Fortran::semantics::FindEquivalenceSet(sym)) {
-                std::string eqName = converter.mangleName(eqObj.symbol);
-                globalOp = builder.getNamedGlobal(eqName);
-                if (globalOp)
-                  break;
-              }
-            }
-          }
-          if (!globalOp)
-            llvm::report_fatal_error("could not retrieve global symbol");
-          std::stringstream ctorName;
-          ctorName << globalName << "_acc_ctor";
-          if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
-                  ctorName.str())) {
-            mlir::Location operandLocation = genOperandLocation(converter, obj);
-            addDeclareAttr(builder, globalOp.getOperation(),
-                mlir::acc::DataClause::acc_copyin);
-            mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
-            modBuilder.setInsertionPointAfter(globalOp);
-            std::stringstream asFortran;
-            asFortran << sym.name().ToString();
-            auto savedIP = builder.saveInsertionPoint();
-            createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
-                                  mlir::acc::CopyinOp,
-                                  mlir::acc::DeclareEnterOp,
-                                  mlir::acc::DeleteOp>(modBuilder, builder,
-                    operandLocation, globalOp,
-                    mlir::acc::DataClause::acc_copyin, ctorName.str(),
+        emitCommonGlobal(obj, mlir::acc::DataClause::acc_copyin,
+            [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
+                fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+                std::stringstream &asFortran, const std::string &ctorName) {
+              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+                                    mlir::acc::CopyinOp,
+                                    mlir::acc::DeclareEnterOp,
+                                    mlir::acc::DeleteOp>(modBuilder, builder,
+                    operandLocation, globalOp, clause, ctorName,
                     /*implicit=*/false, asFortran);
-            std::stringstream dtorName;
-            dtorName << globalName << "_acc_dtor";
-            createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
-                                  mlir::acc::GetDevicePtrOp,
-                                  mlir::acc::DeclareExitOp,
-                                  mlir::acc::DeleteOp>(modBuilder, builder,
-                    operandLocation, globalOp,
-                    mlir::acc::DataClause::acc_copyin, dtorName.str(),
+              std::stringstream dtorName;
+              dtorName << globalOp.getSymName().str() << "_acc_dtor";
+              createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+                                    mlir::acc::GetDevicePtrOp,
+                                    mlir::acc::DeclareExitOp,
+                                    mlir::acc::DeleteOp>(modBuilder, builder,
+                    operandLocation, globalOp, clause, dtorName.str(),
                     /*implicit=*/false, asFortran);
-            builder.restoreInsertionPoint(savedIP);
-          }
-        }
+            });
       }
       auto crtDataStart = dataClauseOperands.size();
       genDeclareDataOperandOperationsWithModifier<mlir::acc::CopyinOp,
@@ -4486,57 +4469,26 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
           copyoutClause->v;
       const auto &accObjectList =
           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
-      // Emit module-level declare for COMMON symbols in this clause.
       for (const auto &obj : accObjectList.v) {
-        Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
-        if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
-            Fortran::semantics::FindCommonBlockContaining(sym)) {
-          std::string globalName = converter.mangleName(sym);
-          fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
-          if (!globalOp) {
-            if (Fortran::semantics::FindEquivalenceSet(sym)) {
-              for (Fortran::semantics::EquivalenceObject eqObj :
-                   *Fortran::semantics::FindEquivalenceSet(sym)) {
-                std::string eqName = converter.mangleName(eqObj.symbol);
-                globalOp = builder.getNamedGlobal(eqName);
-                if (globalOp)
-                  break;
-              }
-            }
-          }
-          if (!globalOp)
-            llvm::report_fatal_error("could not retrieve global symbol");
-          std::stringstream ctorName;
-          ctorName << globalName << "_acc_ctor";
-          if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
-                  ctorName.str())) {
-            mlir::Location operandLocation = genOperandLocation(converter, obj);
-            addDeclareAttr(builder, globalOp.getOperation(),
-                mlir::acc::DataClause::acc_copyout);
-            mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
-            modBuilder.setInsertionPointAfter(globalOp);
-            std::stringstream asFortran;
-            asFortran << sym.name().ToString();
-            auto savedIP = builder.saveInsertionPoint();
-            createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
-                                  mlir::acc::CreateOp,
-                                  mlir::acc::DeclareEnterOp,
-                                  mlir::acc::CopyoutOp>(modBuilder, builder,
-                    operandLocation, globalOp,
-                    mlir::acc::DataClause::acc_copyout, ctorName.str(),
+        emitCommonGlobal(obj, mlir::acc::DataClause::acc_copyout,
+            [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
+                fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+                std::stringstream &asFortran, const std::string &ctorName) {
+              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+                                    mlir::acc::CreateOp,
+                                    mlir::acc::DeclareEnterOp,
+                                    mlir::acc::CopyoutOp>(modBuilder, builder,
+                    operandLocation, globalOp, clause, ctorName,
                     /*implicit=*/false, asFortran);
-            std::stringstream dtorName;
-            dtorName << globalName << "_acc_dtor";
-            createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
-                                  mlir::acc::GetDevicePtrOp,
-                                  mlir::acc::DeclareExitOp,
-                                  mlir::acc::CopyoutOp>(modBuilder, builder,
-                    operandLocation, globalOp,
-                    mlir::acc::DataClause::acc_copyout, dtorName.str(),
+              std::stringstream dtorName;
+              dtorName << globalOp.getSymName().str() << "_acc_dtor";
+              createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+                                    mlir::acc::GetDevicePtrOp,
+                                    mlir::acc::DeclareExitOp,
+                                    mlir::acc::CopyoutOp>(modBuilder, builder,
+                    operandLocation, globalOp, clause, dtorName.str(),
                     /*implicit=*/false, asFortran);
-            builder.restoreInsertionPoint(savedIP);
-          }
-        }
+            });
       }
       auto crtDataStart = dataClauseOperands.size();
       genDeclareDataOperandOperations<mlir::acc::CreateOp,
@@ -4556,49 +4508,19 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
           /*structured=*/true, /*implicit=*/false);
     } else if (const auto *linkClause =
                    std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
-      // Emit module-level declare for COMMON symbols in this clause.
       const auto &linkObjs = linkClause->v;
       for (const auto &obj : linkObjs.v) {
-        Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
-        if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
-            Fortran::semantics::FindCommonBlockContaining(sym)) {
-          std::string globalName = converter.mangleName(sym);
-          fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
-          if (!globalOp) {
-            if (Fortran::semantics::FindEquivalenceSet(sym)) {
-              for (Fortran::semantics::EquivalenceObject eqObj :
-                   *Fortran::semantics::FindEquivalenceSet(sym)) {
-                std::string eqName = converter.mangleName(eqObj.symbol);
-                globalOp = builder.getNamedGlobal(eqName);
-                if (globalOp)
-                  break;
-              }
-            }
-          }
-          if (!globalOp)
-            llvm::report_fatal_error("could not retrieve global symbol");
-          std::stringstream ctorName;
-          ctorName << globalName << "_acc_ctor";
-          if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
-                  ctorName.str())) {
-            mlir::Location operandLocation = genOperandLocation(converter, obj);
-            addDeclareAttr(builder, globalOp.getOperation(),
-                mlir::acc::DataClause::acc_declare_link);
-            mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
-            modBuilder.setInsertionPointAfter(globalOp);
-            std::stringstream asFortran;
-            asFortran << sym.name().ToString();
-            auto savedIP = builder.saveInsertionPoint();
-            createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
-                                  mlir::acc::DeclareLinkOp,
-                                  mlir::acc::DeclareEnterOp,
-                                  mlir::acc::DeclareLinkOp>(modBuilder, builder,
-                    operandLocation, globalOp,
-                    mlir::acc::DataClause::acc_declare_link, ctorName.str(),
+        emitCommonGlobal(obj, mlir::acc::DataClause::acc_declare_link,
+            [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
+                fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+                std::stringstream &asFortran, const std::string &ctorName) {
+              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+                                    mlir::acc::DeclareLinkOp,
+                                    mlir::acc::DeclareEnterOp,
+                                    mlir::acc::DeclareLinkOp>(modBuilder,
+                    builder, operandLocation, globalOp, clause, ctorName,
                     /*implicit=*/false, asFortran);
-            builder.restoreInsertionPoint(savedIP);
-          }
-        }
+            });
       }
       genDeclareDataOperandOperations<mlir::acc::DeclareLinkOp,
                                       mlir::acc::DeclareLinkOp>(
@@ -4608,50 +4530,20 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
     } else if (const auto *deviceResidentClause =
                    std::get_if<Fortran::parser::AccClause::DeviceResident>(
                        &clause.u)) {
-      // Emit module-level declare for COMMON symbols in this clause.
       const auto &devResObjs = deviceResidentClause->v;
       for (const auto &obj : devResObjs.v) {
-        Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
-        if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
-            Fortran::semantics::FindCommonBlockContaining(sym)) {
-          std::string globalName = converter.mangleName(sym);
-          fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
-          if (!globalOp) {
-            if (Fortran::semantics::FindEquivalenceSet(sym)) {
-              for (Fortran::semantics::EquivalenceObject eqObj :
-                   *Fortran::semantics::FindEquivalenceSet(sym)) {
-                std::string eqName = converter.mangleName(eqObj.symbol);
-                globalOp = builder.getNamedGlobal(eqName);
-                if (globalOp)
-                  break;
-              }
-            }
-          }
-          if (!globalOp)
-            llvm::report_fatal_error("could not retrieve global symbol");
-          std::stringstream ctorName;
-          ctorName << globalName << "_acc_ctor";
-          if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
-                  ctorName.str())) {
-            mlir::Location operandLocation = genOperandLocation(converter, obj);
-            addDeclareAttr(builder, globalOp.getOperation(),
-                mlir::acc::DataClause::acc_declare_device_resident);
-            mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
-            modBuilder.setInsertionPointAfter(globalOp);
-            std::stringstream asFortran;
-            asFortran << sym.name().ToString();
-            auto savedIP = builder.saveInsertionPoint();
-            createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
-                                  mlir::acc::DeclareDeviceResidentOp,
-                                  mlir::acc::DeclareEnterOp,
-                                  mlir::acc::DeleteOp>(modBuilder, builder,
-                    operandLocation, globalOp,
-                    mlir::acc::DataClause::acc_declare_device_resident,
-                    ctorName.str(),
+        emitCommonGlobal(obj,
+            mlir::acc::DataClause::acc_declare_device_resident,
+            [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
+                fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+                std::stringstream &asFortran, const std::string &ctorName) {
+              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+                                    mlir::acc::DeclareDeviceResidentOp,
+                                    mlir::acc::DeclareEnterOp,
+                                    mlir::acc::DeleteOp>(modBuilder, builder,
+                    operandLocation, globalOp, clause, ctorName,
                     /*implicit=*/false, asFortran);
-            builder.restoreInsertionPoint(savedIP);
-          }
-        }
+            });
       }
       auto crtDataStart = dataClauseOperands.size();
       genDeclareDataOperandOperations<mlir::acc::DeclareDeviceResidentOp,

>From 3592903f21135f6117623d07634c5d95c8ae6c26 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Wed, 15 Oct 2025 17:24:56 -0700
Subject: [PATCH 03/12] more refactor

---
 flang/lib/Lower/OpenACC.cpp | 83 ++++++++++++++++---------------------
 1 file changed, 35 insertions(+), 48 deletions(-)

diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 37abcffc683d9..e493198fd2b51 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -4138,6 +4138,29 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
   modBuilder.setInsertionPointAfter(declareGlobalOp);
 }
 
+// Small helper to emit a constructor/destructor pair for a given global
+// declare Entry/Exit Op combination.
+template <typename EntryOp, typename ExitOp>
+static void emitCtorDtorPair(mlir::OpBuilder &modBuilder,
+                             fir::FirOpBuilder &builder,
+                             mlir::Location operandLocation,
+                             fir::GlobalOp globalOp,
+                             mlir::acc::DataClause clause,
+                             std::stringstream &asFortran,
+                             const std::string &ctorName) {
+  createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
+                        mlir::acc::DeclareEnterOp, ExitOp>(
+      modBuilder, builder, operandLocation, globalOp, clause, ctorName,
+      /*implicit=*/false, asFortran);
+
+  std::stringstream dtorName;
+  dtorName << globalOp.getSymName().str() << "_acc_dtor";
+  createDeclareGlobalOp<mlir::acc::GlobalDestructorOp, mlir::acc::GetDevicePtrOp,
+                        mlir::acc::DeclareExitOp, ExitOp>(
+      modBuilder, builder, operandLocation, globalOp, clause, dtorName.str(),
+      /*implicit=*/false, asFortran);
+}
+
 template <typename EntryOp>
 static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder,
                                    fir::FirOpBuilder &builder,
@@ -4393,20 +4416,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
             [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
                 fir::GlobalOp globalOp, mlir::acc::DataClause clause,
                 std::stringstream &asFortran, const std::string &ctorName) {
-              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
-                                    mlir::acc::CreateOp,
-                                    mlir::acc::DeclareEnterOp,
-                                    mlir::acc::DeleteOp>(modBuilder, builder,
-                    operandLocation, globalOp, clause, ctorName,
-                    /*implicit=*/false, asFortran);
-              std::stringstream dtorName;
-              dtorName << globalOp.getSymName().str() << "_acc_dtor";
-              createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
-                                    mlir::acc::GetDevicePtrOp,
-                                    mlir::acc::DeclareExitOp,
-                                    mlir::acc::DeleteOp>(modBuilder, builder,
-                    operandLocation, globalOp, clause, dtorName.str(),
-                    /*implicit=*/false, asFortran);
+              emitCtorDtorPair<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
+                  modBuilder, builder, operandLocation, globalOp, clause,
+                  asFortran, ctorName);
             });
       }
       auto crtDataStart = dataClauseOperands.size();
@@ -4437,20 +4449,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
             [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
                 fir::GlobalOp globalOp, mlir::acc::DataClause clause,
                 std::stringstream &asFortran, const std::string &ctorName) {
-              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
-                                    mlir::acc::CopyinOp,
-                                    mlir::acc::DeclareEnterOp,
-                                    mlir::acc::DeleteOp>(modBuilder, builder,
-                    operandLocation, globalOp, clause, ctorName,
-                    /*implicit=*/false, asFortran);
-              std::stringstream dtorName;
-              dtorName << globalOp.getSymName().str() << "_acc_dtor";
-              createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
-                                    mlir::acc::GetDevicePtrOp,
-                                    mlir::acc::DeclareExitOp,
-                                    mlir::acc::DeleteOp>(modBuilder, builder,
-                    operandLocation, globalOp, clause, dtorName.str(),
-                    /*implicit=*/false, asFortran);
+              emitCtorDtorPair<mlir::acc::CopyinOp, mlir::acc::DeleteOp>(
+                  modBuilder, builder, operandLocation, globalOp, clause,
+                  asFortran, ctorName);
             });
       }
       auto crtDataStart = dataClauseOperands.size();
@@ -4474,20 +4475,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
             [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
                 fir::GlobalOp globalOp, mlir::acc::DataClause clause,
                 std::stringstream &asFortran, const std::string &ctorName) {
-              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
-                                    mlir::acc::CreateOp,
-                                    mlir::acc::DeclareEnterOp,
-                                    mlir::acc::CopyoutOp>(modBuilder, builder,
-                    operandLocation, globalOp, clause, ctorName,
-                    /*implicit=*/false, asFortran);
-              std::stringstream dtorName;
-              dtorName << globalOp.getSymName().str() << "_acc_dtor";
-              createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
-                                    mlir::acc::GetDevicePtrOp,
-                                    mlir::acc::DeclareExitOp,
-                                    mlir::acc::CopyoutOp>(modBuilder, builder,
-                    operandLocation, globalOp, clause, dtorName.str(),
-                    /*implicit=*/false, asFortran);
+              emitCtorDtorPair<mlir::acc::CreateOp, mlir::acc::CopyoutOp>(
+                  modBuilder, builder, operandLocation, globalOp, clause,
+                  asFortran, ctorName);
             });
       }
       auto crtDataStart = dataClauseOperands.size();
@@ -4537,12 +4527,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
             [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
                 fir::GlobalOp globalOp, mlir::acc::DataClause clause,
                 std::stringstream &asFortran, const std::string &ctorName) {
-              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
-                                    mlir::acc::DeclareDeviceResidentOp,
-                                    mlir::acc::DeclareEnterOp,
-                                    mlir::acc::DeleteOp>(modBuilder, builder,
-                    operandLocation, globalOp, clause, ctorName,
-                    /*implicit=*/false, asFortran);
+              emitCtorDtorPair<mlir::acc::DeclareDeviceResidentOp,
+                               mlir::acc::DeleteOp>(modBuilder, builder,
+                  operandLocation, globalOp, clause, asFortran, ctorName);
             });
       }
       auto crtDataStart = dataClauseOperands.size();

>From c76338c64ee5b7c452ffb5eba816ae560511a2b4 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Wed, 15 Oct 2025 18:38:03 -0700
Subject: [PATCH 04/12] add a test

---
 flang/lib/Lower/OpenACC.cpp                   |  9 +++++
 .../acc-declare-common-in-function.f90        | 40 +++++++++++++++++++
 2 files changed, 49 insertions(+)
 create mode 100644 flang/test/Lower/OpenACC/acc-declare-common-in-function.f90

diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index e493198fd2b51..f2afc75b7f6b3 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -726,6 +726,10 @@ static void genDeclareDataOperandOperations(
     std::stringstream asFortran;
     mlir::Location operandLocation = genOperandLocation(converter, accObject);
     Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
+    // Skip COMMON/global symbols: handled via global ctor/dtor path in declare.
+    if (symbol.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+        Fortran::semantics::FindCommonBlockContaining(symbol))
+      continue;
     Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
         [&](auto &&s) { return ea.Analyze(s); }, accObject.u);
     fir::factory::AddrAndBoundsInfo info =
@@ -4547,6 +4551,11 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
     }
   }
 
+  // If no structured operands were generated (all objects were COMMON),
+  // do not create a declare region.
+  if (dataClauseOperands.empty())
+    return;
+
   mlir::func::FuncOp funcOp = builder.getFunction();
   auto ops = funcOp.getOps<mlir::acc::DeclareEnterOp>();
   mlir::Value declareToken;
diff --git a/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90 b/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90
new file mode 100644
index 0000000000000..bffbe304c7078
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90
@@ -0,0 +1,40 @@
+! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s
+
+! Verify that a COMMON block declared with OpenACC declare inside a function
+! is lowered as a global declare (acc.global_ctor/dtor) rather than a
+! structured declare.
+
+program p
+  implicit none
+  real :: pi
+  integer :: i
+  common /RIEMANN_COM/ pi
+!$acc declare copyin(/RIEMANN_COM/)
+  data pi/0.0/
+
+! CHECK-DAG: acc.global_ctor @{{.*}}_acc_ctor {
+! CHECK-DAG: %[[ADDR0:.*]] = fir.address_of(@{{.*}}) {acc.declare = #acc.declare<dataClause = acc_copyin>} : {{.*}}
+! CHECK-DAG: acc.declare_enter dataOperands(%{{.*}} : {{.*}})
+! CHECK-DAG: acc.terminator
+! CHECK-DAG: }
+
+! CHECK-DAG: acc.global_dtor @{{.*}}_acc_dtor {
+! CHECK-DAG: %[[ADDR1:.*]] = fir.address_of(@{{.*}}) {acc.declare = #acc.declare<dataClause = acc_copyin>} : !fir.ref<tuple<f32>>
+! CHECK-DAG: %[[GDP:.*]] = acc.getdeviceptr varPtr(%[[ADDR1]] : !fir.ref<tuple<f32>>) -> !fir.ref<tuple<f32>> {dataClause = #acc<data_clause acc_copyin>, {{.*}}}
+! CHECK-DAG: acc.declare_exit dataOperands(%[[GDP]] : !fir.ref<tuple<f32>>)
+! CHECK-DAG: acc.delete accPtr(%[[GDP]] : !fir.ref<tuple<f32>>) {dataClause = #acc<data_clause acc_copyin>{{.*}}}
+! CHECK-DAG: acc.terminator
+! CHECK-DAG: }
+
+contains
+
+  subroutine s()
+    implicit none
+    real :: pi
+    common /RIEMANN_COM/ pi
+!$acc declare copyin(/RIEMANN_COM/)
+  end subroutine s
+
+end program p
+
+

>From bd6d4f98943a0f8b1cd4d81a4971f39f2e060920 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Thu, 16 Oct 2025 07:54:42 -0700
Subject: [PATCH 05/12] change test name

---
 .../test/Lower/OpenACC/acc-declare-common-in-function.f90 | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90 b/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90
index bffbe304c7078..5038f718517ac 100644
--- a/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90
+++ b/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90
@@ -8,8 +8,8 @@ program p
   implicit none
   real :: pi
   integer :: i
-  common /RIEMANN_COM/ pi
-!$acc declare copyin(/RIEMANN_COM/)
+  common /COM/ pi
+!$acc declare copyin(/COM/)
   data pi/0.0/
 
 ! CHECK-DAG: acc.global_ctor @{{.*}}_acc_ctor {
@@ -31,8 +31,8 @@ program p
   subroutine s()
     implicit none
     real :: pi
-    common /RIEMANN_COM/ pi
-!$acc declare copyin(/RIEMANN_COM/)
+    common /COM/ pi
+!$acc declare copyin(/COM/)
   end subroutine s
 
 end program p

>From b3f733ca077b05f50e9aeccbd2443dd56173080e Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 17 Oct 2025 10:34:03 -0700
Subject: [PATCH 06/12] refactor lamda to a standalone function

---
 flang/lib/Lower/OpenACC.cpp | 107 +++++++++++++++++++-----------------
 1 file changed, 58 insertions(+), 49 deletions(-)

diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index f2afc75b7f6b3..410d4d3dad18c 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -4342,6 +4342,55 @@ genGlobalCtorsWithModifier(Fortran::lower::AbstractConverter &converter,
                                   dataClause);
 }
 
+// Emit module-level declare for COMMON symbols referenced by an ACC clause.
+// The emitter functor is responsible for creating ctor/dtor operations.
+template <typename EmitterFn>
+static void emitCommonGlobal(Fortran::lower::AbstractConverter &converter,
+    fir::FirOpBuilder &builder, const Fortran::parser::AccObject &obj,
+    mlir::acc::DataClause clause, EmitterFn &&emitCtorDtor) {
+  Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+  if (!(sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+        Fortran::semantics::FindCommonBlockContaining(sym))) {
+    return;
+  }
+
+  std::string globalName = converter.mangleName(sym);
+  fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+  if (!globalOp) {
+    if (Fortran::semantics::FindEquivalenceSet(sym)) {
+      for (Fortran::semantics::EquivalenceObject eqObj :
+          *Fortran::semantics::FindEquivalenceSet(sym)) {
+        std::string eqName = converter.mangleName(eqObj.symbol);
+        globalOp = builder.getNamedGlobal(eqName);
+        if (globalOp)
+          break;
+      }
+    }
+  }
+  if (!globalOp) {
+    llvm::report_fatal_error("could not retrieve global symbol");
+  }
+
+  std::stringstream ctorName;
+  ctorName << globalName << "_acc_ctor";
+  if (builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+          ctorName.str())) {
+    return;
+  }
+
+  mlir::Location operandLocation = genOperandLocation(converter, obj);
+  addDeclareAttr(builder, globalOp.getOperation(), clause);
+  mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+  modBuilder.setInsertionPointAfter(globalOp);
+  std::stringstream asFortran;
+  asFortran << sym.name().ToString();
+
+  auto savedIP = builder.saveInsertionPoint();
+  emitCtorDtor(modBuilder, operandLocation, globalOp, clause, asFortran,
+      ctorName.str());
+  builder.restoreInsertionPoint(savedIP);
+}
+
 static void
 genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
                      Fortran::semantics::SemanticsContext &semanticsContext,
@@ -4354,50 +4403,6 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
   Fortran::lower::StatementContext stmtCtx;
   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
 
-  // Inline helper to emit module-level declare for COMMON symbols in a clause.
-  auto emitCommonGlobal = [&](const Fortran::parser::AccObject &obj,
-                              mlir::acc::DataClause clause,
-                              auto emitCtorDtor) {
-    Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
-    if (!(sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
-          Fortran::semantics::FindCommonBlockContaining(sym)))
-      return;
-
-    std::string globalName = converter.mangleName(sym);
-    fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
-    if (!globalOp) {
-      if (Fortran::semantics::FindEquivalenceSet(sym)) {
-        for (Fortran::semantics::EquivalenceObject eqObj :
-             *Fortran::semantics::FindEquivalenceSet(sym)) {
-          std::string eqName = converter.mangleName(eqObj.symbol);
-          globalOp = builder.getNamedGlobal(eqName);
-          if (globalOp)
-            break;
-        }
-      }
-    }
-    if (!globalOp)
-      llvm::report_fatal_error("could not retrieve global symbol");
-
-    std::stringstream ctorName;
-    ctorName << globalName << "_acc_ctor";
-    if (builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
-            ctorName.str()))
-      return;
-
-    mlir::Location operandLocation = genOperandLocation(converter, obj);
-    addDeclareAttr(builder, globalOp.getOperation(), clause);
-    mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
-    modBuilder.setInsertionPointAfter(globalOp);
-    std::stringstream asFortran;
-    asFortran << sym.name().ToString();
-
-    auto savedIP = builder.saveInsertionPoint();
-    emitCtorDtor(modBuilder, operandLocation, globalOp, clause, asFortran,
-                 ctorName.str());
-    builder.restoreInsertionPoint(savedIP);
-  };
-
   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
     if (const auto *copyClause =
             std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
@@ -4416,7 +4421,8 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
       const auto &accObjectList =
           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
       for (const auto &obj : accObjectList.v) {
-        emitCommonGlobal(obj, mlir::acc::DataClause::acc_create,
+        emitCommonGlobal(converter, builder, obj,
+            mlir::acc::DataClause::acc_create,
             [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
                 fir::GlobalOp globalOp, mlir::acc::DataClause clause,
                 std::stringstream &asFortran, const std::string &ctorName) {
@@ -4449,7 +4455,8 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
       const auto &copyinObjs =
           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
       for (const auto &obj : copyinObjs.v) {
-        emitCommonGlobal(obj, mlir::acc::DataClause::acc_copyin,
+        emitCommonGlobal(converter, builder, obj,
+            mlir::acc::DataClause::acc_copyin,
             [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
                 fir::GlobalOp globalOp, mlir::acc::DataClause clause,
                 std::stringstream &asFortran, const std::string &ctorName) {
@@ -4475,7 +4482,8 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
       const auto &accObjectList =
           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
       for (const auto &obj : accObjectList.v) {
-        emitCommonGlobal(obj, mlir::acc::DataClause::acc_copyout,
+        emitCommonGlobal(converter, builder, obj,
+            mlir::acc::DataClause::acc_copyout,
             [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
                 fir::GlobalOp globalOp, mlir::acc::DataClause clause,
                 std::stringstream &asFortran, const std::string &ctorName) {
@@ -4504,7 +4512,8 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
                    std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
       const auto &linkObjs = linkClause->v;
       for (const auto &obj : linkObjs.v) {
-        emitCommonGlobal(obj, mlir::acc::DataClause::acc_declare_link,
+        emitCommonGlobal(converter, builder, obj,
+            mlir::acc::DataClause::acc_declare_link,
             [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
                 fir::GlobalOp globalOp, mlir::acc::DataClause clause,
                 std::stringstream &asFortran, const std::string &ctorName) {
@@ -4526,7 +4535,7 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
                        &clause.u)) {
       const auto &devResObjs = deviceResidentClause->v;
       for (const auto &obj : devResObjs.v) {
-        emitCommonGlobal(obj,
+        emitCommonGlobal(converter, builder, obj,
             mlir::acc::DataClause::acc_declare_device_resident,
             [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
                 fir::GlobalOp globalOp, mlir::acc::DataClause clause,

>From 725382f7bd8162cda83485ba1d211bca4e10240e Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 17 Oct 2025 10:55:23 -0700
Subject: [PATCH 07/12] get name using the common block name

---
 flang/lib/Lower/OpenACC.cpp | 42 +++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 16 deletions(-)

diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 410d4d3dad18c..00cfa6a3dadd2 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -4342,8 +4342,30 @@ genGlobalCtorsWithModifier(Fortran::lower::AbstractConverter &converter,
                                   dataClause);
 }
 
-// Emit module-level declare for COMMON symbols referenced by an ACC clause.
-// The emitter functor is responsible for creating ctor/dtor operations.
+static fir::GlobalOp lookupGlobalBySymbolOrEquivalence(
+    Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder,
+    const Fortran::semantics::Symbol &sym) {
+  const Fortran::semantics::Symbol *commonBlock =
+      Fortran::semantics::FindCommonBlockContaining(sym);
+  std::string globalName = commonBlock ? converter.mangleName(*commonBlock)
+                                       : converter.mangleName(sym);
+  if (fir::GlobalOp g = builder.getNamedGlobal(globalName)) {
+    return g;
+  }
+  // Not found: if not a COMMON member, try equivalence members
+  if (!commonBlock) {
+    if (auto *eqSet = Fortran::semantics::FindEquivalenceSet(sym)) {
+      for (Fortran::semantics::EquivalenceObject eqObj : *eqSet) {
+        std::string eqName = converter.mangleName(eqObj.symbol);
+        if (fir::GlobalOp g = builder.getNamedGlobal(eqName)) {
+          return g;
+        }
+      }
+    }
+  }
+  return {};
+}
+
 template <typename EmitterFn>
 static void emitCommonGlobal(Fortran::lower::AbstractConverter &converter,
     fir::FirOpBuilder &builder, const Fortran::parser::AccObject &obj,
@@ -4354,25 +4376,13 @@ static void emitCommonGlobal(Fortran::lower::AbstractConverter &converter,
     return;
   }
 
-  std::string globalName = converter.mangleName(sym);
-  fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
-  if (!globalOp) {
-    if (Fortran::semantics::FindEquivalenceSet(sym)) {
-      for (Fortran::semantics::EquivalenceObject eqObj :
-          *Fortran::semantics::FindEquivalenceSet(sym)) {
-        std::string eqName = converter.mangleName(eqObj.symbol);
-        globalOp = builder.getNamedGlobal(eqName);
-        if (globalOp)
-          break;
-      }
-    }
-  }
+  fir::GlobalOp globalOp = lookupGlobalBySymbolOrEquivalence(converter, builder, sym);
   if (!globalOp) {
     llvm::report_fatal_error("could not retrieve global symbol");
   }
 
   std::stringstream ctorName;
-  ctorName << globalName << "_acc_ctor";
+  ctorName << globalOp.getSymName().str() << "_acc_ctor";
   if (builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
           ctorName.str())) {
     return;

>From 4f8b2dc2eb663041f8701f446ce827b6c53e21ad Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 17 Oct 2025 11:33:10 -0700
Subject: [PATCH 08/12] directly implement in genDeclareDataOperandOperations

---
 flang/lib/Lower/OpenACC.cpp | 263 +++++++++++++++---------------------
 1 file changed, 110 insertions(+), 153 deletions(-)

diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 00cfa6a3dadd2..d5ce1618a7607 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -711,6 +711,84 @@ static void genDataOperandOperations(
   }
 }
 
+template <typename GlobalOp, typename EntryOp, typename DeclareOp,
+          typename ExitOp>
+static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
+                                  fir::FirOpBuilder &builder,
+                                  mlir::Location loc, fir::GlobalOp globalOp,
+                                  mlir::acc::DataClause clause,
+                                  const std::string &declareGlobalName,
+                                  bool implicit, std::stringstream &asFortran) {
+  GlobalOp declareGlobalOp =
+      GlobalOp::create(modBuilder, loc, declareGlobalName);
+  builder.createBlock(&declareGlobalOp.getRegion(),
+                      declareGlobalOp.getRegion().end(), {}, {});
+  builder.setInsertionPointToEnd(&declareGlobalOp.getRegion().back());
+
+  fir::AddrOfOp addrOp = fir::AddrOfOp::create(
+      builder, loc, fir::ReferenceType::get(globalOp.getType()),
+      globalOp.getSymbol());
+  addDeclareAttr(builder, addrOp, clause);
+
+  llvm::SmallVector<mlir::Value> bounds;
+  EntryOp entryOp = createDataEntryOp<EntryOp>(
+      builder, loc, addrOp.getResTy(), asFortran, bounds,
+      /*structured=*/false, implicit, clause, addrOp.getResTy().getType(),
+      /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
+  if constexpr (std::is_same_v<DeclareOp, mlir::acc::DeclareEnterOp>)
+    DeclareOp::create(builder, loc,
+                      mlir::acc::DeclareTokenType::get(entryOp.getContext()),
+                      mlir::ValueRange(entryOp.getAccVar()));
+  else
+    DeclareOp::create(builder, loc, mlir::Value{},
+                      mlir::ValueRange(entryOp.getAccVar()));
+  if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalDestructorOp>) {
+    if constexpr (std::is_same_v<ExitOp, mlir::acc::DeclareLinkOp>) {
+      // No destructor emission for declare link in this path to avoid
+      // complex var/varType/varPtrPtr signatures. The ctor registers the link.
+    } else if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
+                         std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>) {
+      ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
+                     entryOp.getVar(), entryOp.getVarType(),
+                     entryOp.getBounds(), entryOp.getAsyncOperands(),
+                     entryOp.getAsyncOperandsDeviceTypeAttr(),
+                     entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
+                     /*structured=*/false, /*implicit=*/false,
+                     builder.getStringAttr(*entryOp.getName()));
+    } else {
+      ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
+                     entryOp.getBounds(), entryOp.getAsyncOperands(),
+                     entryOp.getAsyncOperandsDeviceTypeAttr(),
+                     entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
+                     /*structured=*/false, /*implicit=*/false,
+                     builder.getStringAttr(*entryOp.getName()));
+    }
+  }
+  mlir::acc::TerminatorOp::create(builder, loc);
+  modBuilder.setInsertionPointAfter(declareGlobalOp);
+}
+
+template <typename EntryOp, typename ExitOp>
+static void emitCtorDtorPair(mlir::OpBuilder &modBuilder,
+                             fir::FirOpBuilder &builder,
+                             mlir::Location operandLocation,
+                             fir::GlobalOp globalOp,
+                             mlir::acc::DataClause clause,
+                             std::stringstream &asFortran,
+                             const std::string &ctorName) {
+  createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
+                        mlir::acc::DeclareEnterOp, ExitOp>(
+      modBuilder, builder, operandLocation, globalOp, clause, ctorName,
+      /*implicit=*/false, asFortran);
+
+  std::stringstream dtorName;
+  dtorName << globalOp.getSymName().str() << "_acc_dtor";
+  createDeclareGlobalOp<mlir::acc::GlobalDestructorOp, mlir::acc::GetDevicePtrOp,
+                        mlir::acc::DeclareExitOp, ExitOp>(
+      modBuilder, builder, operandLocation, globalOp, clause, dtorName.str(),
+      /*implicit=*/false, asFortran);
+}
+
 template <typename EntryOp, typename ExitOp>
 static void genDeclareDataOperandOperations(
     const Fortran::parser::AccObjectList &objectList,
@@ -726,10 +804,36 @@ static void genDeclareDataOperandOperations(
     std::stringstream asFortran;
     mlir::Location operandLocation = genOperandLocation(converter, accObject);
     Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
-    // Skip COMMON/global symbols: handled via global ctor/dtor path in declare.
+    // Handle COMMON/global symbols via module-level ctor/dtor path.
     if (symbol.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
-        Fortran::semantics::FindCommonBlockContaining(symbol))
+        Fortran::semantics::FindCommonBlockContaining(symbol)) {
+      emitCommonGlobal(converter, builder, accObject, dataClause,
+          [&](mlir::OpBuilder &modBuilder, mlir::Location loc,
+              fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+              std::stringstream &asFortranStr, const std::string &ctorName) {
+            if constexpr (std::is_same_v<EntryOp, mlir::acc::DeclareLinkOp>) {
+              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+                                    mlir::acc::DeclareLinkOp,
+                                    mlir::acc::DeclareEnterOp,
+                                    mlir::acc::DeclareLinkOp>(modBuilder,
+                  builder, loc, globalOp, clause, ctorName,
+                  /*implicit=*/false, asFortranStr);
+            } else if constexpr (
+                std::is_same_v<EntryOp, mlir::acc::CreateOp> ||
+                std::is_same_v<EntryOp, mlir::acc::CopyinOp> ||
+                std::is_same_v<EntryOp, mlir::acc::DeclareDeviceResidentOp> ||
+                std::is_same_v<ExitOp, mlir::acc::CopyoutOp>) {
+              emitCtorDtorPair<EntryOp, ExitOp>(
+                  modBuilder, builder, loc, globalOp, clause, asFortranStr,
+                  ctorName);
+            } else {
+              // No module-level ctor/dtor for this clause (e.g., deviceptr,
+              // present). Handled via structured declare region only.
+              return;
+            }
+          });
       continue;
+    }
     Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
         [&](auto &&s) { return ea.Analyze(s); }, accObject.u);
     fir::factory::AddrAndBoundsInfo info =
@@ -4085,86 +4189,6 @@ static void genACC(Fortran::lower::AbstractConverter &converter,
     waitOp.setAsyncAttr(firOpBuilder.getUnitAttr());
 }
 
-template <typename GlobalOp, typename EntryOp, typename DeclareOp,
-          typename ExitOp>
-static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
-                                  fir::FirOpBuilder &builder,
-                                  mlir::Location loc, fir::GlobalOp globalOp,
-                                  mlir::acc::DataClause clause,
-                                  const std::string &declareGlobalName,
-                                  bool implicit, std::stringstream &asFortran) {
-  GlobalOp declareGlobalOp =
-      GlobalOp::create(modBuilder, loc, declareGlobalName);
-  builder.createBlock(&declareGlobalOp.getRegion(),
-                      declareGlobalOp.getRegion().end(), {}, {});
-  builder.setInsertionPointToEnd(&declareGlobalOp.getRegion().back());
-
-  fir::AddrOfOp addrOp = fir::AddrOfOp::create(
-      builder, loc, fir::ReferenceType::get(globalOp.getType()),
-      globalOp.getSymbol());
-  addDeclareAttr(builder, addrOp, clause);
-
-  llvm::SmallVector<mlir::Value> bounds;
-  EntryOp entryOp = createDataEntryOp<EntryOp>(
-      builder, loc, addrOp.getResTy(), asFortran, bounds,
-      /*structured=*/false, implicit, clause, addrOp.getResTy().getType(),
-      /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
-  if constexpr (std::is_same_v<DeclareOp, mlir::acc::DeclareEnterOp>)
-    DeclareOp::create(builder, loc,
-                      mlir::acc::DeclareTokenType::get(entryOp.getContext()),
-                      mlir::ValueRange(entryOp.getAccVar()));
-  else
-    DeclareOp::create(builder, loc, mlir::Value{},
-                      mlir::ValueRange(entryOp.getAccVar()));
-  if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalDestructorOp>) {
-    if constexpr (std::is_same_v<ExitOp, mlir::acc::DeclareLinkOp>) {
-      // No destructor emission for declare link in this path to avoid
-      // complex var/varType/varPtrPtr signatures. The ctor registers the link.
-    } else if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
-                         std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>) {
-      ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
-                     entryOp.getVar(), entryOp.getVarType(),
-                     entryOp.getBounds(), entryOp.getAsyncOperands(),
-                     entryOp.getAsyncOperandsDeviceTypeAttr(),
-                     entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
-                     /*structured=*/false, /*implicit=*/false,
-                     builder.getStringAttr(*entryOp.getName()));
-    } else {
-      ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
-                     entryOp.getBounds(), entryOp.getAsyncOperands(),
-                     entryOp.getAsyncOperandsDeviceTypeAttr(),
-                     entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
-                     /*structured=*/false, /*implicit=*/false,
-                     builder.getStringAttr(*entryOp.getName()));
-    }
-  }
-  mlir::acc::TerminatorOp::create(builder, loc);
-  modBuilder.setInsertionPointAfter(declareGlobalOp);
-}
-
-// Small helper to emit a constructor/destructor pair for a given global
-// declare Entry/Exit Op combination.
-template <typename EntryOp, typename ExitOp>
-static void emitCtorDtorPair(mlir::OpBuilder &modBuilder,
-                             fir::FirOpBuilder &builder,
-                             mlir::Location operandLocation,
-                             fir::GlobalOp globalOp,
-                             mlir::acc::DataClause clause,
-                             std::stringstream &asFortran,
-                             const std::string &ctorName) {
-  createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
-                        mlir::acc::DeclareEnterOp, ExitOp>(
-      modBuilder, builder, operandLocation, globalOp, clause, ctorName,
-      /*implicit=*/false, asFortran);
-
-  std::stringstream dtorName;
-  dtorName << globalOp.getSymName().str() << "_acc_dtor";
-  createDeclareGlobalOp<mlir::acc::GlobalDestructorOp, mlir::acc::GetDevicePtrOp,
-                        mlir::acc::DeclareExitOp, ExitOp>(
-      modBuilder, builder, operandLocation, globalOp, clause, dtorName.str(),
-      /*implicit=*/false, asFortran);
-}
-
 template <typename EntryOp>
 static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder,
                                    fir::FirOpBuilder &builder,
@@ -4426,22 +4450,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
                                dataClauseOperands.end());
     } else if (const auto *createClause =
                    std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
-      const Fortran::parser::AccObjectListWithModifier &listWithModifier =
-          createClause->v;
-      const auto &accObjectList =
-          std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
-      for (const auto &obj : accObjectList.v) {
-        emitCommonGlobal(converter, builder, obj,
-            mlir::acc::DataClause::acc_create,
-            [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
-                fir::GlobalOp globalOp, mlir::acc::DataClause clause,
-                std::stringstream &asFortran, const std::string &ctorName) {
-              emitCtorDtorPair<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
-                  modBuilder, builder, operandLocation, globalOp, clause,
-                  asFortran, ctorName);
-            });
-      }
       auto crtDataStart = dataClauseOperands.size();
+      const auto &accObjectList =
+          std::get<Fortran::parser::AccObjectList>(createClause->v.t);
       genDeclareDataOperandOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
           accObjectList, converter, semanticsContext, stmtCtx,
           dataClauseOperands, mlir::acc::DataClause::acc_create,
@@ -4461,20 +4472,6 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
                                   dataClauseOperands.end());
     } else if (const auto *copyinClause =
                    std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
-      const auto &listWithModifier = copyinClause->v;
-      const auto &copyinObjs =
-          std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
-      for (const auto &obj : copyinObjs.v) {
-        emitCommonGlobal(converter, builder, obj,
-            mlir::acc::DataClause::acc_copyin,
-            [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
-                fir::GlobalOp globalOp, mlir::acc::DataClause clause,
-                std::stringstream &asFortran, const std::string &ctorName) {
-              emitCtorDtorPair<mlir::acc::CopyinOp, mlir::acc::DeleteOp>(
-                  modBuilder, builder, operandLocation, globalOp, clause,
-                  asFortran, ctorName);
-            });
-      }
       auto crtDataStart = dataClauseOperands.size();
       genDeclareDataOperandOperationsWithModifier<mlir::acc::CopyinOp,
                                                   mlir::acc::DeleteOp>(
@@ -4487,22 +4484,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
     } else if (const auto *copyoutClause =
                    std::get_if<Fortran::parser::AccClause::Copyout>(
                        &clause.u)) {
-      const Fortran::parser::AccObjectListWithModifier &listWithModifier =
-          copyoutClause->v;
-      const auto &accObjectList =
-          std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
-      for (const auto &obj : accObjectList.v) {
-        emitCommonGlobal(converter, builder, obj,
-            mlir::acc::DataClause::acc_copyout,
-            [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
-                fir::GlobalOp globalOp, mlir::acc::DataClause clause,
-                std::stringstream &asFortran, const std::string &ctorName) {
-              emitCtorDtorPair<mlir::acc::CreateOp, mlir::acc::CopyoutOp>(
-                  modBuilder, builder, operandLocation, globalOp, clause,
-                  asFortran, ctorName);
-            });
-      }
       auto crtDataStart = dataClauseOperands.size();
+      const auto &accObjectList =
+          std::get<Fortran::parser::AccObjectList>(copyoutClause->v.t);
       genDeclareDataOperandOperations<mlir::acc::CreateOp,
                                       mlir::acc::CopyoutOp>(
           accObjectList, converter, semanticsContext, stmtCtx,
@@ -4520,21 +4504,6 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
           /*structured=*/true, /*implicit=*/false);
     } else if (const auto *linkClause =
                    std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
-      const auto &linkObjs = linkClause->v;
-      for (const auto &obj : linkObjs.v) {
-        emitCommonGlobal(converter, builder, obj,
-            mlir::acc::DataClause::acc_declare_link,
-            [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
-                fir::GlobalOp globalOp, mlir::acc::DataClause clause,
-                std::stringstream &asFortran, const std::string &ctorName) {
-              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
-                                    mlir::acc::DeclareLinkOp,
-                                    mlir::acc::DeclareEnterOp,
-                                    mlir::acc::DeclareLinkOp>(modBuilder,
-                    builder, operandLocation, globalOp, clause, ctorName,
-                    /*implicit=*/false, asFortran);
-            });
-      }
       genDeclareDataOperandOperations<mlir::acc::DeclareLinkOp,
                                       mlir::acc::DeclareLinkOp>(
           linkClause->v, converter, semanticsContext, stmtCtx,
@@ -4543,18 +4512,6 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
     } else if (const auto *deviceResidentClause =
                    std::get_if<Fortran::parser::AccClause::DeviceResident>(
                        &clause.u)) {
-      const auto &devResObjs = deviceResidentClause->v;
-      for (const auto &obj : devResObjs.v) {
-        emitCommonGlobal(converter, builder, obj,
-            mlir::acc::DataClause::acc_declare_device_resident,
-            [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
-                fir::GlobalOp globalOp, mlir::acc::DataClause clause,
-                std::stringstream &asFortran, const std::string &ctorName) {
-              emitCtorDtorPair<mlir::acc::DeclareDeviceResidentOp,
-                               mlir::acc::DeleteOp>(modBuilder, builder,
-                  operandLocation, globalOp, clause, asFortran, ctorName);
-            });
-      }
       auto crtDataStart = dataClauseOperands.size();
       genDeclareDataOperandOperations<mlir::acc::DeclareDeviceResidentOp,
                                       mlir::acc::DeleteOp>(

>From d39629b432363b6829445d137da4c2811d5b4afb Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 17 Oct 2025 11:35:00 -0700
Subject: [PATCH 09/12] format

---
 flang/lib/Lower/OpenACC.cpp | 69 +++++++++++++++++++------------------
 1 file changed, 36 insertions(+), 33 deletions(-)

diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index d5ce1618a7607..5bcfb6c9e6bc8 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -769,13 +769,11 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
 }
 
 template <typename EntryOp, typename ExitOp>
-static void emitCtorDtorPair(mlir::OpBuilder &modBuilder,
-                             fir::FirOpBuilder &builder,
-                             mlir::Location operandLocation,
-                             fir::GlobalOp globalOp,
-                             mlir::acc::DataClause clause,
-                             std::stringstream &asFortran,
-                             const std::string &ctorName) {
+static void
+emitCtorDtorPair(mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder,
+                 mlir::Location operandLocation, fir::GlobalOp globalOp,
+                 mlir::acc::DataClause clause, std::stringstream &asFortran,
+                 const std::string &ctorName) {
   createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
                         mlir::acc::DeclareEnterOp, ExitOp>(
       modBuilder, builder, operandLocation, globalOp, clause, ctorName,
@@ -783,10 +781,11 @@ static void emitCtorDtorPair(mlir::OpBuilder &modBuilder,
 
   std::stringstream dtorName;
   dtorName << globalOp.getSymName().str() << "_acc_dtor";
-  createDeclareGlobalOp<mlir::acc::GlobalDestructorOp, mlir::acc::GetDevicePtrOp,
-                        mlir::acc::DeclareExitOp, ExitOp>(
-      modBuilder, builder, operandLocation, globalOp, clause, dtorName.str(),
-      /*implicit=*/false, asFortran);
+  createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+                        mlir::acc::GetDevicePtrOp, mlir::acc::DeclareExitOp,
+                        ExitOp>(modBuilder, builder, operandLocation, globalOp,
+                                clause, dtorName.str(),
+                                /*implicit=*/false, asFortran);
 }
 
 template <typename EntryOp, typename ExitOp>
@@ -807,25 +806,26 @@ static void genDeclareDataOperandOperations(
     // Handle COMMON/global symbols via module-level ctor/dtor path.
     if (symbol.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
         Fortran::semantics::FindCommonBlockContaining(symbol)) {
-      emitCommonGlobal(converter, builder, accObject, dataClause,
+      emitCommonGlobal(
+          converter, builder, accObject, dataClause,
           [&](mlir::OpBuilder &modBuilder, mlir::Location loc,
               fir::GlobalOp globalOp, mlir::acc::DataClause clause,
               std::stringstream &asFortranStr, const std::string &ctorName) {
             if constexpr (std::is_same_v<EntryOp, mlir::acc::DeclareLinkOp>) {
-              createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
-                                    mlir::acc::DeclareLinkOp,
-                                    mlir::acc::DeclareEnterOp,
-                                    mlir::acc::DeclareLinkOp>(modBuilder,
-                  builder, loc, globalOp, clause, ctorName,
+              createDeclareGlobalOp<
+                  mlir::acc::GlobalConstructorOp, mlir::acc::DeclareLinkOp,
+                  mlir::acc::DeclareEnterOp, mlir::acc::DeclareLinkOp>(
+                  modBuilder, builder, loc, globalOp, clause, ctorName,
                   /*implicit=*/false, asFortranStr);
-            } else if constexpr (
-                std::is_same_v<EntryOp, mlir::acc::CreateOp> ||
-                std::is_same_v<EntryOp, mlir::acc::CopyinOp> ||
-                std::is_same_v<EntryOp, mlir::acc::DeclareDeviceResidentOp> ||
-                std::is_same_v<ExitOp, mlir::acc::CopyoutOp>) {
-              emitCtorDtorPair<EntryOp, ExitOp>(
-                  modBuilder, builder, loc, globalOp, clause, asFortranStr,
-                  ctorName);
+            } else if constexpr (std::is_same_v<EntryOp, mlir::acc::CreateOp> ||
+                                 std::is_same_v<EntryOp, mlir::acc::CopyinOp> ||
+                                 std::is_same_v<
+                                     EntryOp,
+                                     mlir::acc::DeclareDeviceResidentOp> ||
+                                 std::is_same_v<ExitOp, mlir::acc::CopyoutOp>) {
+              emitCtorDtorPair<EntryOp, ExitOp>(modBuilder, builder, loc,
+                                                globalOp, clause, asFortranStr,
+                                                ctorName);
             } else {
               // No module-level ctor/dtor for this clause (e.g., deviceptr,
               // present). Handled via structured declare region only.
@@ -3506,7 +3506,6 @@ genACCHostDataOp(Fortran::lower::AbstractConverter &converter,
 
   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
 
-
   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
     mlir::Location clauseLocation = converter.genLocation(clause.source);
     if (const auto *ifClause =
@@ -4366,9 +4365,10 @@ genGlobalCtorsWithModifier(Fortran::lower::AbstractConverter &converter,
                                   dataClause);
 }
 
-static fir::GlobalOp lookupGlobalBySymbolOrEquivalence(
-    Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder,
-    const Fortran::semantics::Symbol &sym) {
+static fir::GlobalOp
+lookupGlobalBySymbolOrEquivalence(Fortran::lower::AbstractConverter &converter,
+                                  fir::FirOpBuilder &builder,
+                                  const Fortran::semantics::Symbol &sym) {
   const Fortran::semantics::Symbol *commonBlock =
       Fortran::semantics::FindCommonBlockContaining(sym);
   std::string globalName = commonBlock ? converter.mangleName(*commonBlock)
@@ -4392,15 +4392,18 @@ static fir::GlobalOp lookupGlobalBySymbolOrEquivalence(
 
 template <typename EmitterFn>
 static void emitCommonGlobal(Fortran::lower::AbstractConverter &converter,
-    fir::FirOpBuilder &builder, const Fortran::parser::AccObject &obj,
-    mlir::acc::DataClause clause, EmitterFn &&emitCtorDtor) {
+                             fir::FirOpBuilder &builder,
+                             const Fortran::parser::AccObject &obj,
+                             mlir::acc::DataClause clause,
+                             EmitterFn &&emitCtorDtor) {
   Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
   if (!(sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
         Fortran::semantics::FindCommonBlockContaining(sym))) {
     return;
   }
 
-  fir::GlobalOp globalOp = lookupGlobalBySymbolOrEquivalence(converter, builder, sym);
+  fir::GlobalOp globalOp =
+      lookupGlobalBySymbolOrEquivalence(converter, builder, sym);
   if (!globalOp) {
     llvm::report_fatal_error("could not retrieve global symbol");
   }
@@ -4421,7 +4424,7 @@ static void emitCommonGlobal(Fortran::lower::AbstractConverter &converter,
 
   auto savedIP = builder.saveInsertionPoint();
   emitCtorDtor(modBuilder, operandLocation, globalOp, clause, asFortran,
-      ctorName.str());
+               ctorName.str());
   builder.restoreInsertionPoint(savedIP);
 }
 

>From d12237499f8fbbbfdd400d71e1a0fa3f43f4c1af Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 17 Oct 2025 13:51:10 -0700
Subject: [PATCH 10/12] formatting

---
 flang/lib/Lower/OpenACC.cpp | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 5bcfb6c9e6bc8..fd830ae83d779 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -711,7 +711,7 @@ static void genDataOperandOperations(
   }
 }
 
-template <typename GlobalOp, typename EntryOp, typename DeclareOp,
+template <typename GlobalCtorOrDtorOp, typename EntryOp, typename DeclareOp,
           typename ExitOp>
 static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
                                   fir::FirOpBuilder &builder,
@@ -719,8 +719,8 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
                                   mlir::acc::DataClause clause,
                                   const std::string &declareGlobalName,
                                   bool implicit, std::stringstream &asFortran) {
-  GlobalOp declareGlobalOp =
-      GlobalOp::create(modBuilder, loc, declareGlobalName);
+  GlobalCtorOrDtorOp declareGlobalOp =
+      GlobalCtorOrDtorOp::create(modBuilder, loc, declareGlobalName);
   builder.createBlock(&declareGlobalOp.getRegion(),
                       declareGlobalOp.getRegion().end(), {}, {});
   builder.setInsertionPointToEnd(&declareGlobalOp.getRegion().back());
@@ -742,7 +742,8 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
   else
     DeclareOp::create(builder, loc, mlir::Value{},
                       mlir::ValueRange(entryOp.getAccVar()));
-  if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalDestructorOp>) {
+  if constexpr (std::is_same_v<GlobalCtorOrDtorOp,
+                               mlir::acc::GlobalDestructorOp>) {
     if constexpr (std::is_same_v<ExitOp, mlir::acc::DeclareLinkOp>) {
       // No destructor emission for declare link in this path to avoid
       // complex var/varType/varPtrPtr signatures. The ctor registers the link.
@@ -4398,22 +4399,19 @@ static void emitCommonGlobal(Fortran::lower::AbstractConverter &converter,
                              EmitterFn &&emitCtorDtor) {
   Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
   if (!(sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
-        Fortran::semantics::FindCommonBlockContaining(sym))) {
+        Fortran::semantics::FindCommonBlockContaining(sym)))
     return;
-  }
 
   fir::GlobalOp globalOp =
       lookupGlobalBySymbolOrEquivalence(converter, builder, sym);
-  if (!globalOp) {
+  if (!globalOp)
     llvm::report_fatal_error("could not retrieve global symbol");
-  }
 
   std::stringstream ctorName;
   ctorName << globalOp.getSymName().str() << "_acc_ctor";
   if (builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
-          ctorName.str())) {
+          ctorName.str()))
     return;
-  }
 
   mlir::Location operandLocation = genOperandLocation(converter, obj);
   addDeclareAttr(builder, globalOp.getOperation(), clause);

>From 6306bee8dafb759d7d2f24330df91d47ef283f34 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 17 Oct 2025 13:52:05 -0700
Subject: [PATCH 11/12] formatting

---
 flang/lib/Lower/OpenACC.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index fd830ae83d779..ed496349b4ee6 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -4382,9 +4382,8 @@ lookupGlobalBySymbolOrEquivalence(Fortran::lower::AbstractConverter &converter,
     if (auto *eqSet = Fortran::semantics::FindEquivalenceSet(sym)) {
       for (Fortran::semantics::EquivalenceObject eqObj : *eqSet) {
         std::string eqName = converter.mangleName(eqObj.symbol);
-        if (fir::GlobalOp g = builder.getNamedGlobal(eqName)) {
+        if (fir::GlobalOp g = builder.getNamedGlobal(eqName))
           return g;
-        }
       }
     }
   }

>From 9fdd3180dcf4e596798a0edb89a167a4c557bba8 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 17 Oct 2025 15:42:05 -0700
Subject: [PATCH 12/12] formatting

---
 flang/lib/Lower/OpenACC.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index ed496349b4ee6..e0b9201bf4ec1 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -4379,8 +4379,9 @@ lookupGlobalBySymbolOrEquivalence(Fortran::lower::AbstractConverter &converter,
   }
   // Not found: if not a COMMON member, try equivalence members
   if (!commonBlock) {
-    if (auto *eqSet = Fortran::semantics::FindEquivalenceSet(sym)) {
-      for (Fortran::semantics::EquivalenceObject eqObj : *eqSet) {
+    if (const Fortran::semantics::EquivalenceSet *eqSet =
+            Fortran::semantics::FindEquivalenceSet(sym)) {
+      for (const Fortran::semantics::EquivalenceObject &eqObj : *eqSet) {
         std::string eqName = converter.mangleName(eqObj.symbol);
         if (fir::GlobalOp g = builder.getNamedGlobal(eqName))
           return g;



More information about the flang-commits mailing list