Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang][openacc] Support variable in equivalence in declare directive #71242

Merged
merged 3 commits into from
Nov 6, 2023

Conversation

clementval
Copy link
Contributor

A variable in equivalence share the storage units with one or more objects. When lowered to FIR, the global created for the equivalence has the name of one of the object. The variable also has an offset in the storage unit.
This patch takes all of this into account for variable part of equivalence used in a declare directive.

@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir openacc labels Nov 3, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Nov 3, 2023

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

@llvm/pr-subscribers-openacc

Author: Valentin Clement (バレンタイン クレメン) (clementval)

Changes

A variable in equivalence share the storage units with one or more objects. When lowered to FIR, the global created for the equivalence has the name of one of the object. The variable also has an offset in the storage unit.
This patch takes all of this into account for variable part of equivalence used in a declare directive.


Full diff: https://github.com/llvm/llvm-project/pull/71242.diff

2 Files Affected:

  • (modified) flang/lib/Lower/OpenACC.cpp (+64-22)
  • (modified) flang/test/Lower/OpenACC/HLFIR/acc-declare.f90 (+58)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 809fd3b3be7cfdf..7808e94ed7c7346 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -27,6 +27,7 @@
 #include "flang/Optimizer/Builder/Todo.h"
 #include "flang/Parser/parse-tree.h"
 #include "flang/Semantics/expression.h"
+#include "flang/Semantics/scope.h"
 #include "flang/Semantics/tools.h"
 #include "llvm/Frontend/OpenACC/ACC.h.inc"
 
@@ -2740,33 +2741,40 @@ static void genACC(Fortran::lower::AbstractConverter &converter,
 
 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, bool implicit) {
-  std::stringstream declareGlobalName;
-
-  if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalConstructorOp>)
-    declareGlobalName << globalOp.getSymName().str() << "_acc_ctor";
-  else if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalDestructorOp>)
-    declareGlobalName << globalOp.getSymName().str() << "_acc_dtor";
-
+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::optional<std::size_t> &offset, mlir::Type aliasType,
+                      std::stringstream &asFortran) {
   GlobalOp declareGlobalOp =
-      modBuilder.create<GlobalOp>(loc, declareGlobalName.str());
+      modBuilder.create<GlobalOp>(loc, declareGlobalName);
   builder.createBlock(&declareGlobalOp.getRegion(),
                       declareGlobalOp.getRegion().end(), {}, {});
   builder.setInsertionPointToEnd(&declareGlobalOp.getRegion().back());
+  mlir::Value entryAddr;
 
   fir::AddrOfOp addrOp = builder.create<fir::AddrOfOp>(
       loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol());
-  addDeclareAttr(builder, addrOp.getOperation(), clause);
+  entryAddr = addrOp.getResTy();
+  // If the variable in the declare clause is part of an equivalence it has an
+  // offset.
+  if (offset) {
+    mlir::Type i8Ptr = builder.getRefType(builder.getI8Type());
+    mlir::Value off =
+        builder.createIntegerConstant(loc, builder.getIndexType(), *offset);
+    mlir::Value aliasAddr = builder.create<fir::CoordinateOp>(
+        loc, i8Ptr, addrOp.getResTy(), mlir::ValueRange{off});
+    entryAddr =
+        builder.createConvert(loc, fir::PointerType::get(aliasType), aliasAddr);
+  }
+  addDeclareAttr(builder, entryAddr.getDefiningOp(), clause);
 
-  std::stringstream asFortran;
-  asFortran << Fortran::lower::mangle::demangleName(globalOp.getSymName());
   llvm::SmallVector<mlir::Value> bounds;
   EntryOp entryOp = createDataEntryOp<EntryOp>(
-      builder, loc, addrOp.getResTy(), asFortran, bounds,
-      /*structured=*/false, implicit, clause, addrOp.getResTy().getType());
+      builder, loc, entryAddr, asFortran, bounds,
+      /*structured=*/false, implicit, clause, entryAddr.getType());
   builder.create<DeclareOp>(loc, mlir::ValueRange(entryOp.getAccPtr()));
   mlir::Value varPtr;
   if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalDestructorOp>) {
@@ -2904,8 +2912,39 @@ static void genGlobalCtors(Fortran::lower::AbstractConverter &converter,
                           designator)) {
                 std::string globalName = converter.mangleName(*name->symbol);
                 fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
-                if (!globalOp)
-                  llvm::report_fatal_error("could not retrieve global symbol");
+                std::stringstream declareGlobalCtorName;
+                declareGlobalCtorName << globalName << "_acc_ctor";
+                std::stringstream declareGlobalDtorName;
+                declareGlobalDtorName << globalName << "_acc_dtor";
+                std::optional<std::size_t> offset = std::nullopt;
+                mlir::Type aliasType;
+
+                std::stringstream asFortran;
+                asFortran << name->symbol->name().ToString();
+
+                if (!globalOp) {
+                  if (Fortran::semantics::FindEquivalenceSet(*name->symbol)) {
+                    for (Fortran::semantics::EquivalenceObject eqObj :
+                         *Fortran::semantics::FindEquivalenceSet(
+                             *name->symbol)) {
+                      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");
+
+                    offset = name->symbol->GetUltimate().offset();
+                    aliasType = converter.genType(name->symbol->GetUltimate());
+                  } else {
+                    llvm::report_fatal_error(
+                        "could not retrieve global symbol");
+                  }
+                }
+
                 addDeclareAttr(builder, globalOp.getOperation(), clause);
                 auto crtPos = builder.saveInsertionPoint();
                 modBuilder.setInsertionPointAfter(globalOp);
@@ -2915,7 +2954,8 @@ static void genGlobalCtors(Fortran::lower::AbstractConverter &converter,
                                         mlir::acc::CopyinOp,
                                         mlir::acc::DeclareEnterOp, ExitOp>(
                       modBuilder, builder, operandLocation, globalOp, clause,
-                      /*implicit=*/true);
+                      declareGlobalCtorName.str(), /*implicit=*/true, offset,
+                      aliasType, asFortran);
                   createDeclareAllocFunc<EntryOp>(
                       modBuilder, builder, operandLocation, globalOp, clause);
                   if constexpr (!std::is_same_v<EntryOp, ExitOp>)
@@ -2925,14 +2965,16 @@ static void genGlobalCtors(Fortran::lower::AbstractConverter &converter,
                   createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
                                         mlir::acc::DeclareEnterOp, ExitOp>(
                       modBuilder, builder, operandLocation, globalOp, clause,
-                      /*implicit=*/false);
+                      declareGlobalCtorName.str(), /*implicit=*/false, offset,
+                      aliasType, asFortran);
                 }
                 if constexpr (!std::is_same_v<EntryOp, ExitOp>) {
                   createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
                                         mlir::acc::GetDevicePtrOp,
                                         mlir::acc::DeclareExitOp, ExitOp>(
                       modBuilder, builder, operandLocation, globalOp, clause,
-                      /*implicit=*/false);
+                      declareGlobalDtorName.str(), /*implicit=*/false, offset,
+                      aliasType, asFortran);
                 }
                 builder.restoreInsertionPoint(crtPos);
               }
diff --git a/flang/test/Lower/OpenACC/HLFIR/acc-declare.f90 b/flang/test/Lower/OpenACC/HLFIR/acc-declare.f90
index 0a45967ce82ef3e..6cca57a2504e2b9 100644
--- a/flang/test/Lower/OpenACC/HLFIR/acc-declare.f90
+++ b/flang/test/Lower/OpenACC/HLFIR/acc-declare.f90
@@ -258,3 +258,61 @@ module acc_declare_allocatable_test
 ! ALL:         acc.delete accPtr(%[[DEVICEPTR]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) {dataClause = #acc<data_clause acc_create>, name = "data1", structured = false}
 ! ALL:         acc.terminator
 ! ALL:       }
+
+
+module acc_declare_equivalent
+  integer, parameter :: n = 10
+  real :: v1(n)
+  real :: v2(n)
+  equivalence(v1(1), v2(1))
+  !$acc declare create(v2)
+end module
+
+! ALL-LABEL: acc.global_ctor @_QMacc_declare_equivalentEv2_acc_ctor {
+! ALL-DAG:     %[[C0:.*]] = arith.constant 0 : index
+! ALL-DAG:     %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalentEv1) : !fir.ref<!fir.array<40xi8>>
+! ALL:         %[[COORD:.*]] = fir.coordinate_of %[[ADDR]], %[[C0]] : (!fir.ref<!fir.array<40xi8>>, index) -> !fir.ref<i8>
+! ALL:         %[[CONV:.*]] = fir.convert %[[COORD]] {acc.declare = #acc.declare<dataClause =  acc_create>} : (!fir.ref<i8>) -> !fir.ptr<!fir.array<10xf32>>
+! ALL:         %[[CREATE:.*]] = acc.create varPtr(%[[CONV]] : !fir.ptr<!fir.array<10xf32>>) -> !fir.ptr<!fir.array<10xf32>> {name = "v2", structured = false}
+! ALL:         acc.declare_enter dataOperands(%[[CREATE]] : !fir.ptr<!fir.array<10xf32>>)
+! ALL:         acc.terminator
+! ALL:       }
+
+! ALL-LABEL:  acc.global_dtor @_QMacc_declare_equivalentEv2_acc_dtor {
+! ALL-DAG:      %[[C0:.*]] = arith.constant 0 : index
+! ALL-DAG:      %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalentEv1) : !fir.ref<!fir.array<40xi8>>
+! ALL:          %[[COORD:.*]] = fir.coordinate_of %[[ADDR]], %[[C0]] : (!fir.ref<!fir.array<40xi8>>, index) -> !fir.ref<i8>
+! ALL:          %[[CONV:.*]] = fir.convert %[[COORD]] {acc.declare = #acc.declare<dataClause =  acc_create>} : (!fir.ref<i8>) -> !fir.ptr<!fir.array<10xf32>>
+! ALL:          %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[CONV]] : !fir.ptr<!fir.array<10xf32>>) -> !fir.ptr<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_create>, name = "v2", structured = false}
+! ALL:          acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.ptr<!fir.array<10xf32>>)
+! ALL:          acc.delete accPtr(%[[DEVICEPTR]] : !fir.ptr<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_create>, name = "v2", structured = false}
+! ALL:          acc.terminator
+! ALL:        }
+
+module acc_declare_equivalent2
+  real :: v1(10)
+  real :: v2(5)
+  equivalence(v1(6), v2(1))
+  !$acc declare create(v2)
+end module
+
+! ALL-LABEL: acc.global_ctor @_QMacc_declare_equivalent2Ev2_acc_ctor {
+! ALL-DAG:     %[[C20:.*]] = arith.constant 20 : index
+! ALL-DAG:     %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalent2Ev1) : !fir.ref<!fir.array<40xi8>>
+! ALL:         %[[COORD:.*]] = fir.coordinate_of %[[ADDR]], %[[C20]] : (!fir.ref<!fir.array<40xi8>>, index) -> !fir.ref<i8>
+! ALL:         %[[CONV:.*]] = fir.convert %[[COORD]] {acc.declare = #acc.declare<dataClause =  acc_create>} : (!fir.ref<i8>) -> !fir.ptr<!fir.array<5xf32>>
+! ALL:         %[[CREATE:.*]] = acc.create varPtr(%[[CONV]] : !fir.ptr<!fir.array<5xf32>>) -> !fir.ptr<!fir.array<5xf32>> {name = "v2", structured = false}
+! ALL:         acc.declare_enter dataOperands(%[[CREATE]] : !fir.ptr<!fir.array<5xf32>>)
+! ALL:         acc.terminator
+! ALL:       }
+
+! ALL-LABEL: acc.global_dtor @_QMacc_declare_equivalent2Ev2_acc_dtor {
+! ALL-DAG:     %[[C20:.*]] = arith.constant 20 : index
+! ALL-DAG:     %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalent2Ev1) : !fir.ref<!fir.array<40xi8>>
+! ALL:         %[[COORD:.*]] = fir.coordinate_of %[[ADDR]], %[[C20]] : (!fir.ref<!fir.array<40xi8>>, index) -> !fir.ref<i8>
+! ALL:         %[[CONV:.*]] = fir.convert %[[COORD]] {acc.declare = #acc.declare<dataClause =  acc_create>} : (!fir.ref<i8>) -> !fir.ptr<!fir.array<5xf32>>
+! ALL:         %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[CONV]] : !fir.ptr<!fir.array<5xf32>>) -> !fir.ptr<!fir.array<5xf32>> {dataClause = #acc<data_clause acc_create>, name = "v2", structured = false}
+! ALL:         acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.ptr<!fir.array<5xf32>>)
+! ALL:         acc.delete accPtr(%[[DEVICEPTR]] : !fir.ptr<!fir.array<5xf32>>) {dataClause = #acc<data_clause acc_create>, name = "v2", structured = false}
+! ALL:         acc.terminator
+! ALL:       }

Copy link

github-actions bot commented Nov 6, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@vzakhari vzakhari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thank you!

@clementval clementval merged commit fdf3823 into llvm:main Nov 6, 2023
3 checks passed
@clementval clementval deleted the acc_declare_equivalence branch November 6, 2023 22:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:fir-hlfir flang Flang issues not falling into any other category openacc
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants