[flang-commits] [flang] 83fa975 - [flang][openacc] Handle array section and derived-type components operands

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Sat Aug 13 11:40:37 PDT 2022


Author: Valentin Clement
Date: 2022-08-13T20:40:31+02:00
New Revision: 83fa97567949ce16d58b62ecff48930efb1d80bb

URL: https://github.com/llvm/llvm-project/commit/83fa97567949ce16d58b62ecff48930efb1d80bb
DIFF: https://github.com/llvm/llvm-project/commit/83fa97567949ce16d58b62ecff48930efb1d80bb.diff

LOG: [flang][openacc] Handle array section and derived-type components operands

This patch lowers correctly operands with array section
and derived-type component.

Depends on D131764

Reviewed By: razvanlupusoru

Differential Revision: https://reviews.llvm.org/D131765

Added: 
    flang/test/Lower/OpenACC/acc-data-operands.f90

Modified: 
    flang/include/flang/Lower/OpenACC.h
    flang/lib/Lower/Bridge.cpp
    flang/lib/Lower/OpenACC.cpp
    flang/test/Semantics/OpenACC/acc-data.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h
index b3cd70b8e03cb..95cc617531226 100644
--- a/flang/include/flang/Lower/OpenACC.h
+++ b/flang/include/flang/Lower/OpenACC.h
@@ -19,6 +19,10 @@ struct OpenACCConstruct;
 struct OpenACCDeclarativeConstruct;
 } // namespace parser
 
+namespace semantics {
+class SemanticsContext;
+}
+
 namespace lower {
 
 class AbstractConverter;
@@ -27,8 +31,9 @@ namespace pft {
 struct Evaluation;
 } // namespace pft
 
-void genOpenACCConstruct(AbstractConverter &, pft::Evaluation &,
-                         const parser::OpenACCConstruct &);
+void genOpenACCConstruct(AbstractConverter &,
+                         Fortran::semantics::SemanticsContext &,
+                         pft::Evaluation &, const parser::OpenACCConstruct &);
 void genOpenACCDeclarativeConstruct(
     AbstractConverter &, pft::Evaluation &,
     const parser::OpenACCDeclarativeConstruct &);

diff  --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 22938b3c8c193..521782125de8c 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -1631,7 +1631,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
   void genFIR(const Fortran::parser::OpenACCConstruct &acc) {
     mlir::OpBuilder::InsertPoint insertPt = builder->saveInsertionPoint();
-    genOpenACCConstruct(*this, getEval(), acc);
+    genOpenACCConstruct(*this, bridge.getSemanticsContext(), getEval(), acc);
     for (Fortran::lower::pft::Evaluation &e : getEval().getNestedEvaluations())
       genFIR(e);
     builder->restoreInsertionPoint(insertPt);

diff  --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 4b55c8ba6c00d..9d525cec784e3 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -19,6 +19,7 @@
 #include "flang/Optimizer/Builder/FIRBuilder.h"
 #include "flang/Optimizer/Builder/Todo.h"
 #include "flang/Parser/parse-tree.h"
+#include "flang/Semantics/expression.h"
 #include "flang/Semantics/tools.h"
 #include "mlir/Dialect/OpenACC/OpenACC.h"
 #include "llvm/Frontend/OpenACC/ACC.h.inc"
@@ -32,9 +33,12 @@ getDesignatorNameIfDataRef(const Fortran::parser::Designator &designator) {
   return dataRef ? std::get_if<Fortran::parser::Name>(&dataRef->u) : nullptr;
 }
 
-static void genObjectList(const Fortran::parser::AccObjectList &objectList,
-                          Fortran::lower::AbstractConverter &converter,
-                          llvm::SmallVectorImpl<mlir::Value> &operands) {
+static void
+genObjectList(const Fortran::parser::AccObjectList &objectList,
+              Fortran::lower::AbstractConverter &converter,
+              Fortran::semantics::SemanticsContext &semanticsContext,
+              Fortran::lower::StatementContext &stmtCtx,
+              llvm::SmallVectorImpl<mlir::Value> &operands) {
   auto addOperands = [&](Fortran::lower::SymbolRef sym) {
     const auto variable = converter.getSymbolAddress(sym);
     // TODO: Might need revisiting to handle for non-shared clauses
@@ -47,24 +51,60 @@ static void genObjectList(const Fortran::parser::AccObjectList &objectList,
     }
   };
 
+  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+
   for (const auto &accObject : objectList.v) {
-    std::visit(Fortran::common::visitors{
-                   [&](const Fortran::parser::Designator &designator) {
-                     if (const auto *name =
-                             getDesignatorNameIfDataRef(designator)) {
-                       addOperands(*name->symbol);
-                     }
-                   },
-                   [&](const Fortran::parser::Name &name) {
-                     addOperands(*name.symbol);
-                   }},
-               accObject.u);
+    std::visit(
+        Fortran::common::visitors{
+            [&](const Fortran::parser::Designator &designator) {
+              mlir::Location operandLocation =
+                  converter.genLocation(designator.source);
+              if (auto expr{Fortran::semantics::AnalyzeExpr(semanticsContext,
+                                                            designator)}) {
+                if ((*expr).Rank() > 0 &&
+                    Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
+                        designator)) {
+                  // Array sections.
+                  fir::ExtendedValue exV =
+                      converter.genExprBox(operandLocation, *expr, stmtCtx);
+                  mlir::Value section = fir::getBase(exV);
+                  auto mem = builder.create<fir::AllocaOp>(
+                      operandLocation, section.getType(), /*pinned=*/false);
+                  builder.create<fir::StoreOp>(operandLocation, section, mem);
+                  operands.push_back(mem);
+                } else if (Fortran::parser::Unwrap<
+                               Fortran::parser::StructureComponent>(
+                               designator)) {
+                  // Derived type components.
+                  fir::ExtendedValue fieldAddr =
+                      converter.genExprAddr(operandLocation, *expr, stmtCtx);
+                  operands.push_back(fir::getBase(fieldAddr));
+                } else {
+                  // Scalar or full array.
+                  if (const auto *dataRef{std::get_if<Fortran::parser::DataRef>(
+                          &designator.u)}) {
+                    const Fortran::parser::Name &name =
+                        Fortran::parser::GetLastName(*dataRef);
+                    addOperands(*name.symbol);
+                  } else { // Unsupported
+                    TODO(operandLocation,
+                         "Unsupported type of OpenACC operand");
+                  }
+                }
+              }
+            },
+            [&](const Fortran::parser::Name &name) {
+              addOperands(*name.symbol);
+            }},
+        accObject.u);
   }
 }
 
 template <typename Clause>
 static void genObjectListWithModifier(
     const Clause *x, Fortran::lower::AbstractConverter &converter,
+    Fortran::semantics::SemanticsContext &semanticsContext,
+    Fortran::lower::StatementContext &stmtCtx,
     Fortran::parser::AccDataModifier::Modifier mod,
     llvm::SmallVectorImpl<mlir::Value> &operandsWithModifier,
     llvm::SmallVectorImpl<mlir::Value> &operands) {
@@ -75,9 +115,11 @@ static void genObjectListWithModifier(
       std::get<std::optional<Fortran::parser::AccDataModifier>>(
           listWithModifier.t);
   if (modifier && (*modifier).v == mod) {
-    genObjectList(accObjectList, converter, operandsWithModifier);
+    genObjectList(accObjectList, converter, semanticsContext, stmtCtx,
+                  operandsWithModifier);
   } else {
-    genObjectList(accObjectList, converter, operands);
+    genObjectList(accObjectList, converter, semanticsContext, stmtCtx,
+                  operands);
   }
 }
 
@@ -210,9 +252,10 @@ static void genWaitClause(Fortran::lower::AbstractConverter &converter,
 static mlir::acc::LoopOp
 createLoopOp(Fortran::lower::AbstractConverter &converter,
              mlir::Location currentLocation,
+             Fortran::semantics::SemanticsContext &semanticsContext,
+             Fortran::lower::StatementContext &stmtCtx,
              const Fortran::parser::AccClauseList &accClauseList) {
   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
-  Fortran::lower::StatementContext stmtCtx;
 
   mlir::Value workerNum;
   mlir::Value vectorNum;
@@ -286,7 +329,8 @@ createLoopOp(Fortran::lower::AbstractConverter &converter,
     } else if (const auto *privateClause =
                    std::get_if<Fortran::parser::AccClause::Private>(
                        &clause.u)) {
-      genObjectList(privateClause->v, converter, privateOperands);
+      genObjectList(privateClause->v, converter, semanticsContext, stmtCtx,
+                    privateOperands);
     }
     // Reduction clause is left out for the moment as the clause will probably
     // end up having its own operation.
@@ -336,6 +380,7 @@ createLoopOp(Fortran::lower::AbstractConverter &converter,
 }
 
 static void genACC(Fortran::lower::AbstractConverter &converter,
+                   Fortran::semantics::SemanticsContext &semanticsContext,
                    Fortran::lower::pft::Evaluation &eval,
                    const Fortran::parser::OpenACCLoopConstruct &loopConstruct) {
 
@@ -346,17 +391,21 @@ static void genACC(Fortran::lower::AbstractConverter &converter,
 
   mlir::Location currentLocation =
       converter.genLocation(beginLoopDirective.source);
+  Fortran::lower::StatementContext stmtCtx;
 
   if (loopDirective.v == llvm::acc::ACCD_loop) {
     const auto &accClauseList =
         std::get<Fortran::parser::AccClauseList>(beginLoopDirective.t);
-    createLoopOp(converter, currentLocation, accClauseList);
+    createLoopOp(converter, currentLocation, semanticsContext, stmtCtx,
+                 accClauseList);
   }
 }
 
 static mlir::acc::ParallelOp
 createParallelOp(Fortran::lower::AbstractConverter &converter,
                  mlir::Location currentLocation,
+                 Fortran::semantics::SemanticsContext &semanticsContext,
+                 Fortran::lower::StatementContext &stmtCtx,
                  const Fortran::parser::AccClauseList &accClauseList) {
 
   // Parallel operation operands
@@ -381,7 +430,6 @@ createParallelOp(Fortran::lower::AbstractConverter &converter,
   bool addSelfAttr = false;
 
   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
-  Fortran::lower::StatementContext stmtCtx;
 
   // Lower clauses values mapped to operands.
   // Keep track of each group of operands separatly as clauses can appear
@@ -448,49 +496,56 @@ createParallelOp(Fortran::lower::AbstractConverter &converter,
       }
     } else if (const auto *copyClause =
                    std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
-      genObjectList(copyClause->v, converter, copyOperands);
+      genObjectList(copyClause->v, converter, semanticsContext, stmtCtx,
+                    copyOperands);
     } else if (const auto *copyinClause =
                    std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
       genObjectListWithModifier<Fortran::parser::AccClause::Copyin>(
-          copyinClause, converter,
+          copyinClause, converter, semanticsContext, stmtCtx,
           Fortran::parser::AccDataModifier::Modifier::ReadOnly,
           copyinReadonlyOperands, copyinOperands);
     } else if (const auto *copyoutClause =
                    std::get_if<Fortran::parser::AccClause::Copyout>(
                        &clause.u)) {
       genObjectListWithModifier<Fortran::parser::AccClause::Copyout>(
-          copyoutClause, converter,
+          copyoutClause, converter, semanticsContext, stmtCtx,
           Fortran::parser::AccDataModifier::Modifier::Zero, copyoutZeroOperands,
           copyoutOperands);
     } else if (const auto *createClause =
                    std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
       genObjectListWithModifier<Fortran::parser::AccClause::Create>(
-          createClause, converter,
+          createClause, converter, semanticsContext, stmtCtx,
           Fortran::parser::AccDataModifier::Modifier::Zero, createZeroOperands,
           createOperands);
     } else if (const auto *noCreateClause =
                    std::get_if<Fortran::parser::AccClause::NoCreate>(
                        &clause.u)) {
-      genObjectList(noCreateClause->v, converter, noCreateOperands);
+      genObjectList(noCreateClause->v, converter, semanticsContext, stmtCtx,
+                    noCreateOperands);
     } else if (const auto *presentClause =
                    std::get_if<Fortran::parser::AccClause::Present>(
                        &clause.u)) {
-      genObjectList(presentClause->v, converter, presentOperands);
+      genObjectList(presentClause->v, converter, semanticsContext, stmtCtx,
+                    presentOperands);
     } else if (const auto *devicePtrClause =
                    std::get_if<Fortran::parser::AccClause::Deviceptr>(
                        &clause.u)) {
-      genObjectList(devicePtrClause->v, converter, devicePtrOperands);
+      genObjectList(devicePtrClause->v, converter, semanticsContext, stmtCtx,
+                    devicePtrOperands);
     } else if (const auto *attachClause =
                    std::get_if<Fortran::parser::AccClause::Attach>(&clause.u)) {
-      genObjectList(attachClause->v, converter, attachOperands);
+      genObjectList(attachClause->v, converter, semanticsContext, stmtCtx,
+                    attachOperands);
     } else if (const auto *privateClause =
                    std::get_if<Fortran::parser::AccClause::Private>(
                        &clause.u)) {
-      genObjectList(privateClause->v, converter, privateOperands);
+      genObjectList(privateClause->v, converter, semanticsContext, stmtCtx,
+                    privateOperands);
     } else if (const auto *firstprivateClause =
                    std::get_if<Fortran::parser::AccClause::Firstprivate>(
                        &clause.u)) {
-      genObjectList(firstprivateClause->v, converter, firstprivateOperands);
+      genObjectList(firstprivateClause->v, converter, semanticsContext, stmtCtx,
+                    firstprivateOperands);
     }
   }
 
@@ -539,12 +594,17 @@ createParallelOp(Fortran::lower::AbstractConverter &converter,
 static void
 genACCParallelOp(Fortran::lower::AbstractConverter &converter,
                  mlir::Location currentLocation,
+                 Fortran::semantics::SemanticsContext &semanticsContext,
+                 Fortran::lower::StatementContext &stmtCtx,
                  const Fortran::parser::AccClauseList &accClauseList) {
-  createParallelOp(converter, currentLocation, accClauseList);
+  createParallelOp(converter, currentLocation, semanticsContext, stmtCtx,
+                   accClauseList);
 }
 
 static void genACCDataOp(Fortran::lower::AbstractConverter &converter,
                          mlir::Location currentLocation,
+                         Fortran::semantics::SemanticsContext &semanticsContext,
+                         Fortran::lower::StatementContext &stmtCtx,
                          const Fortran::parser::AccClauseList &accClauseList) {
   mlir::Value ifCond;
   llvm::SmallVector<mlir::Value> copyOperands, copyinOperands,
@@ -553,7 +613,6 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter,
       deviceptrOperands, attachOperands;
 
   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
-  Fortran::lower::StatementContext stmtCtx;
 
   // Lower clauses values mapped to operands.
   // Keep track of each group of operands separatly as clauses can appear
@@ -565,45 +624,50 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter,
       genIfClause(converter, clauseLocation, ifClause, ifCond, stmtCtx);
     } else if (const auto *copyClause =
                    std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
-      genObjectList(copyClause->v, converter, copyOperands);
+      genObjectList(copyClause->v, converter, semanticsContext, stmtCtx,
+                    copyOperands);
     } else if (const auto *copyinClause =
                    std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
       genObjectListWithModifier<Fortran::parser::AccClause::Copyin>(
-          copyinClause, converter,
+          copyinClause, converter, semanticsContext, stmtCtx,
           Fortran::parser::AccDataModifier::Modifier::ReadOnly,
           copyinReadonlyOperands, copyinOperands);
     } else if (const auto *copyoutClause =
                    std::get_if<Fortran::parser::AccClause::Copyout>(
                        &clause.u)) {
       genObjectListWithModifier<Fortran::parser::AccClause::Copyout>(
-          copyoutClause, converter,
+          copyoutClause, converter, semanticsContext, stmtCtx,
           Fortran::parser::AccDataModifier::Modifier::Zero, copyoutZeroOperands,
           copyoutOperands);
     } else if (const auto *createClause =
                    std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
       genObjectListWithModifier<Fortran::parser::AccClause::Create>(
-          createClause, converter,
+          createClause, converter, semanticsContext, stmtCtx,
           Fortran::parser::AccDataModifier::Modifier::Zero, createZeroOperands,
           createOperands);
     } else if (const auto *noCreateClause =
                    std::get_if<Fortran::parser::AccClause::NoCreate>(
                        &clause.u)) {
-      genObjectList(noCreateClause->v, converter, noCreateOperands);
+      genObjectList(noCreateClause->v, converter, semanticsContext, stmtCtx,
+                    noCreateOperands);
     } else if (const auto *presentClause =
                    std::get_if<Fortran::parser::AccClause::Present>(
                        &clause.u)) {
-      genObjectList(presentClause->v, converter, presentOperands);
+      genObjectList(presentClause->v, converter, semanticsContext, stmtCtx,
+                    presentOperands);
     } else if (const auto *deviceptrClause =
                    std::get_if<Fortran::parser::AccClause::Deviceptr>(
                        &clause.u)) {
-      genObjectList(deviceptrClause->v, converter, deviceptrOperands);
+      genObjectList(deviceptrClause->v, converter, semanticsContext, stmtCtx,
+                    deviceptrOperands);
     } else if (const auto *attachClause =
                    std::get_if<Fortran::parser::AccClause::Attach>(&clause.u)) {
-      genObjectList(attachClause->v, converter, attachOperands);
+      genObjectList(attachClause->v, converter, semanticsContext, stmtCtx,
+                    attachOperands);
     }
   }
 
-  // Prepare the operand segement size attribute and the operands value range.
+  // Prepare the operand segment size attribute and the operands value range.
   llvm::SmallVector<mlir::Value> operands;
   llvm::SmallVector<int32_t> operandSegments;
   addOperand(operands, operandSegments, ifCond);
@@ -625,6 +689,7 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter,
 
 static void
 genACC(Fortran::lower::AbstractConverter &converter,
+       Fortran::semantics::SemanticsContext &semanticsContext,
        Fortran::lower::pft::Evaluation &eval,
        const Fortran::parser::OpenACCBlockConstruct &blockConstruct) {
   const auto &beginBlockDirective =
@@ -635,24 +700,32 @@ genACC(Fortran::lower::AbstractConverter &converter,
       std::get<Fortran::parser::AccClauseList>(beginBlockDirective.t);
 
   mlir::Location currentLocation = converter.genLocation(blockDirective.source);
+  Fortran::lower::StatementContext stmtCtx;
 
   if (blockDirective.v == llvm::acc::ACCD_parallel) {
-    genACCParallelOp(converter, currentLocation, accClauseList);
+    genACCParallelOp(converter, currentLocation, semanticsContext, stmtCtx,
+                     accClauseList);
   } else if (blockDirective.v == llvm::acc::ACCD_data) {
-    genACCDataOp(converter, currentLocation, accClauseList);
+    genACCDataOp(converter, currentLocation, semanticsContext, stmtCtx,
+                 accClauseList);
   }
 }
 
 static void
 genACCParallelLoopOps(Fortran::lower::AbstractConverter &converter,
                       mlir::Location currentLocation,
+                      Fortran::semantics::SemanticsContext &semanticsContext,
+                      Fortran::lower::StatementContext &stmtCtx,
                       const Fortran::parser::AccClauseList &accClauseList) {
-  createParallelOp(converter, currentLocation, accClauseList);
-  createLoopOp(converter, currentLocation, accClauseList);
+  createParallelOp(converter, currentLocation, semanticsContext, stmtCtx,
+                   accClauseList);
+  createLoopOp(converter, currentLocation, semanticsContext, stmtCtx,
+               accClauseList);
 }
 
 static void
 genACC(Fortran::lower::AbstractConverter &converter,
+       Fortran::semantics::SemanticsContext &semanticsContext,
        Fortran::lower::pft::Evaluation &eval,
        const Fortran::parser::OpenACCCombinedConstruct &combinedConstruct) {
   const auto &beginCombinedDirective =
@@ -664,11 +737,13 @@ genACC(Fortran::lower::AbstractConverter &converter,
 
   mlir::Location currentLocation =
       converter.genLocation(beginCombinedDirective.source);
+  Fortran::lower::StatementContext stmtCtx;
 
   if (combinedDirective.v == llvm::acc::ACCD_kernels_loop) {
     TODO(currentLocation, "OpenACC Kernels Loop construct not lowered yet!");
   } else if (combinedDirective.v == llvm::acc::ACCD_parallel_loop) {
-    genACCParallelLoopOps(converter, currentLocation, accClauseList);
+    genACCParallelLoopOps(converter, currentLocation, semanticsContext, stmtCtx,
+                          accClauseList);
   } else if (combinedDirective.v == llvm::acc::ACCD_serial_loop) {
     TODO(currentLocation, "OpenACC Serial Loop construct not lowered yet!");
   } else {
@@ -679,6 +754,8 @@ genACC(Fortran::lower::AbstractConverter &converter,
 static void
 genACCEnterDataOp(Fortran::lower::AbstractConverter &converter,
                   mlir::Location currentLocation,
+                  Fortran::semantics::SemanticsContext &semanticsContext,
+                  Fortran::lower::StatementContext &stmtCtx,
                   const Fortran::parser::AccClauseList &accClauseList) {
   mlir::Value ifCond, async, waitDevnum;
   llvm::SmallVector<mlir::Value> copyinOperands, createOperands,
@@ -691,7 +768,6 @@ genACCEnterDataOp(Fortran::lower::AbstractConverter &converter,
   bool addWaitAttr = false;
 
   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
-  Fortran::lower::StatementContext stmtCtx;
 
   // Lower clauses values mapped to operands.
   // Keep track of each group of operands separatly as clauses can appear
@@ -714,16 +790,18 @@ genACCEnterDataOp(Fortran::lower::AbstractConverter &converter,
           copyinClause->v;
       const auto &accObjectList =
           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
-      genObjectList(accObjectList, converter, copyinOperands);
+      genObjectList(accObjectList, converter, semanticsContext, stmtCtx,
+                    copyinOperands);
     } else if (const auto *createClause =
                    std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
       genObjectListWithModifier<Fortran::parser::AccClause::Create>(
-          createClause, converter,
+          createClause, converter, semanticsContext, stmtCtx,
           Fortran::parser::AccDataModifier::Modifier::Zero, createZeroOperands,
           createOperands);
     } else if (const auto *attachClause =
                    std::get_if<Fortran::parser::AccClause::Attach>(&clause.u)) {
-      genObjectList(attachClause->v, converter, attachOperands);
+      genObjectList(attachClause->v, converter, semanticsContext, stmtCtx,
+                    attachOperands);
     } else {
       llvm::report_fatal_error(
           "Unknown clause in ENTER DATA directive lowering");
@@ -754,6 +832,8 @@ genACCEnterDataOp(Fortran::lower::AbstractConverter &converter,
 static void
 genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
                  mlir::Location currentLocation,
+                 Fortran::semantics::SemanticsContext &semanticsContext,
+                 Fortran::lower::StatementContext &stmtCtx,
                  const Fortran::parser::AccClauseList &accClauseList) {
   mlir::Value ifCond, async, waitDevnum;
   llvm::SmallVector<mlir::Value> copyoutOperands, deleteOperands,
@@ -767,7 +847,6 @@ genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
   bool addFinalizeAttr = false;
 
   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
-  Fortran::lower::StatementContext stmtCtx;
 
   // Lower clauses values mapped to operands.
   // Keep track of each group of operands separatly as clauses can appear
@@ -791,13 +870,16 @@ genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
           copyoutClause->v;
       const auto &accObjectList =
           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
-      genObjectList(accObjectList, converter, copyoutOperands);
+      genObjectList(accObjectList, converter, semanticsContext, stmtCtx,
+                    copyoutOperands);
     } else if (const auto *deleteClause =
                    std::get_if<Fortran::parser::AccClause::Delete>(&clause.u)) {
-      genObjectList(deleteClause->v, converter, deleteOperands);
+      genObjectList(deleteClause->v, converter, semanticsContext, stmtCtx,
+                    deleteOperands);
     } else if (const auto *detachClause =
                    std::get_if<Fortran::parser::AccClause::Detach>(&clause.u)) {
-      genObjectList(detachClause->v, converter, detachOperands);
+      genObjectList(detachClause->v, converter, semanticsContext, stmtCtx,
+                    detachOperands);
     } else if (std::get_if<Fortran::parser::AccClause::Finalize>(&clause.u)) {
       addFinalizeAttr = true;
     }
@@ -870,6 +952,8 @@ genACCInitShutdownOp(Fortran::lower::AbstractConverter &converter,
 static void
 genACCUpdateOp(Fortran::lower::AbstractConverter &converter,
                mlir::Location currentLocation,
+               Fortran::semantics::SemanticsContext &semanticsContext,
+               Fortran::lower::StatementContext &stmtCtx,
                const Fortran::parser::AccClauseList &accClauseList) {
   mlir::Value ifCond, async, waitDevnum;
   llvm::SmallVector<mlir::Value> hostOperands, deviceOperands, waitOperands,
@@ -883,7 +967,6 @@ genACCUpdateOp(Fortran::lower::AbstractConverter &converter,
   bool addIfPresentAttr = false;
 
   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
-  Fortran::lower::StatementContext stmtCtx;
 
   // Lower clauses values mapped to operands.
   // Keep track of each group of operands separatly as clauses can appear
@@ -907,10 +990,12 @@ genACCUpdateOp(Fortran::lower::AbstractConverter &converter,
                           deviceTypeOperands, stmtCtx);
     } else if (const auto *hostClause =
                    std::get_if<Fortran::parser::AccClause::Host>(&clause.u)) {
-      genObjectList(hostClause->v, converter, hostOperands);
+      genObjectList(hostClause->v, converter, semanticsContext, stmtCtx,
+                    hostOperands);
     } else if (const auto *deviceClause =
                    std::get_if<Fortran::parser::AccClause::Device>(&clause.u)) {
-      genObjectList(deviceClause->v, converter, deviceOperands);
+      genObjectList(deviceClause->v, converter, semanticsContext, stmtCtx,
+                    deviceOperands);
     }
   }
 
@@ -938,6 +1023,7 @@ genACCUpdateOp(Fortran::lower::AbstractConverter &converter,
 
 static void
 genACC(Fortran::lower::AbstractConverter &converter,
+       Fortran::semantics::SemanticsContext &semanticsContext,
        Fortran::lower::pft::Evaluation &eval,
        const Fortran::parser::OpenACCStandaloneConstruct &standaloneConstruct) {
   const auto &standaloneDirective =
@@ -947,11 +1033,14 @@ genACC(Fortran::lower::AbstractConverter &converter,
 
   mlir::Location currentLocation =
       converter.genLocation(standaloneDirective.source);
+  Fortran::lower::StatementContext stmtCtx;
 
   if (standaloneDirective.v == llvm::acc::Directive::ACCD_enter_data) {
-    genACCEnterDataOp(converter, currentLocation, accClauseList);
+    genACCEnterDataOp(converter, currentLocation, semanticsContext, stmtCtx,
+                      accClauseList);
   } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_exit_data) {
-    genACCExitDataOp(converter, currentLocation, accClauseList);
+    genACCExitDataOp(converter, currentLocation, semanticsContext, stmtCtx,
+                     accClauseList);
   } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_init) {
     genACCInitShutdownOp<mlir::acc::InitOp>(converter, currentLocation,
                                             accClauseList);
@@ -961,7 +1050,8 @@ genACC(Fortran::lower::AbstractConverter &converter,
   } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_set) {
     TODO(currentLocation, "OpenACC set directive not lowered yet!");
   } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_update) {
-    genACCUpdateOp(converter, currentLocation, accClauseList);
+    genACCUpdateOp(converter, currentLocation, semanticsContext, stmtCtx,
+                   accClauseList);
   }
 }
 
@@ -1035,24 +1125,25 @@ static void genACC(Fortran::lower::AbstractConverter &converter,
 
 void Fortran::lower::genOpenACCConstruct(
     Fortran::lower::AbstractConverter &converter,
+    Fortran::semantics::SemanticsContext &semanticsContext,
     Fortran::lower::pft::Evaluation &eval,
     const Fortran::parser::OpenACCConstruct &accConstruct) {
 
   std::visit(
       common::visitors{
           [&](const Fortran::parser::OpenACCBlockConstruct &blockConstruct) {
-            genACC(converter, eval, blockConstruct);
+            genACC(converter, semanticsContext, eval, blockConstruct);
           },
           [&](const Fortran::parser::OpenACCCombinedConstruct
                   &combinedConstruct) {
-            genACC(converter, eval, combinedConstruct);
+            genACC(converter, semanticsContext, eval, combinedConstruct);
           },
           [&](const Fortran::parser::OpenACCLoopConstruct &loopConstruct) {
-            genACC(converter, eval, loopConstruct);
+            genACC(converter, semanticsContext, eval, loopConstruct);
           },
           [&](const Fortran::parser::OpenACCStandaloneConstruct
                   &standaloneConstruct) {
-            genACC(converter, eval, standaloneConstruct);
+            genACC(converter, semanticsContext, eval, standaloneConstruct);
           },
           [&](const Fortran::parser::OpenACCCacheConstruct &cacheConstruct) {
             TODO(converter.genLocation(cacheConstruct.source),

diff  --git a/flang/test/Lower/OpenACC/acc-data-operands.f90 b/flang/test/Lower/OpenACC/acc-data-operands.f90
new file mode 100644
index 0000000000000..4df81e8a1475f
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-data-operands.f90
@@ -0,0 +1,124 @@
+! This test checks lowering of complex OpenACC data operands.
+
+! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s
+
+module acc_data_operand
+
+  type wrapper
+    real :: data(100)
+  end type
+
+contains
+
+! Testing array sections as operands
+subroutine acc_operand_array_section()
+  real, dimension(100) :: a
+
+  !$acc data copyin(a(1:50)) copyout(a(51:100))
+  !$acc end data
+
+  !CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_section
+
+  !CHECK: %[[ARR:.*]] = fir.alloca !fir.array<100xf32>
+
+  !CHECK: %[[C1:.*]] = fir.convert %c1_i32 : (i32) -> i64
+  !CHECK: %[[LB1:.*]] = fir.convert %[[C1]] : (i64) -> index
+  !CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64
+  !CHECK: %[[STEP1:.*]] = fir.convert %[[C1_I64]] : (i64) -> index
+  !CHECK: %[[C50:.*]] = arith.constant 50 : i32
+  !CHECK: %[[C50_I64:.*]] = fir.convert %[[C50]] : (i32) -> i64
+  !CHECK: %[[UB1:.*]] = fir.convert %[[C50_I64]] : (i64) -> index
+  !CHECK: %[[SHAPE1:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
+  !CHECK: %[[SLICE1:.*]] = fir.slice %[[LB1]], %[[UB1]], %[[STEP1]] : (index, index, index) -> !fir.slice<1>
+  !CHECK: %[[ARR_SECTION1:.*]] = fir.embox %[[ARR]](%[[SHAPE1]]) [%[[SLICE1]]] : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box<!fir.array<50xf32>>
+  !CHECK: %[[MEM1:.*]] = fir.alloca !fir.box<!fir.array<50xf32>>
+  !CHECK: fir.store %[[ARR_SECTION1]] to %[[MEM1]] : !fir.ref<!fir.box<!fir.array<50xf32>>>
+
+  !CHECK: %[[C51:.*]] = arith.constant 51 : i32
+  !CHECK: %[[C51_I64:.*]] = fir.convert %[[C51]] : (i32) -> i64
+  !CHECK: %[[LB2:.*]] = fir.convert %[[C51_I64]] : (i64) -> index
+  !CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64
+  !CHECK: %[[STEP2:.*]] = fir.convert %[[C1_I64]] : (i64) -> index
+  !CHECK: %[[C100:.*]] = arith.constant 100 : i32
+  !CHECK: %[[C100_I64:.*]] = fir.convert %[[C100]] : (i32) -> i64
+  !CHECK: %[[UB2:.*]] = fir.convert %[[C100_I64]] : (i64) -> index
+  !CHECK: %[[SHAPE2:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
+  !CHECK: %[[SLICE2:.*]] = fir.slice %[[LB2]], %[[UB2]], %[[STEP2]] : (index, index, index) -> !fir.slice<1>
+  !CHECK: %[[ARR_SECTION2:.*]] = fir.embox %[[ARR]](%[[SHAPE2]]) [%[[SLICE2]]] : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box<!fir.array<50xf32>>
+  !CHECK: %[[MEM2:.*]] = fir.alloca !fir.box<!fir.array<50xf32>>
+  !CHECK: fir.store %[[ARR_SECTION2]] to %[[MEM2]] : !fir.ref<!fir.box<!fir.array<50xf32>>>
+
+  !CHECK: acc.data copyin(%[[MEM1]] : !fir.ref<!fir.box<!fir.array<50xf32>>>) copyout(%[[MEM2]] : !fir.ref<!fir.box<!fir.array<50xf32>>>)
+
+end subroutine
+
+! Testing array sections of a derived-type component
+subroutine acc_operand_array_section_component()
+
+  type(wrapper) :: w
+
+  !$acc data copy(w%data(1:20))
+  !$acc end data
+
+  !CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_section_component
+  !CHECK: %[[W:.*]] = fir.alloca !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>
+  !CHECK: %[[FIELD_INDEX:.*]] = fir.field_index data, !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>
+  !CHECK: %[[DATA_COORD:.*]] = fir.coordinate_of %[[W]], %[[FIELD_INDEX]] : (!fir.ref<!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>>, !fir.field) -> !fir.ref<!fir.array<100xf32>>
+  !CHECK: %[[C1:.*]] = arith.constant 1 : i32
+  !CHECK: %[[C1_I64:.*]] = fir.convert %[[C1]] : (i32) -> i64
+  !CHECK: %[[LB:.*]] = fir.convert %3 : (i64) -> index
+  !CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64
+  !CHECK: %[[STEP:.*]] = fir.convert %[[C1_I64]] : (i64) -> index
+  !CHECK: %[[C20:.*]] = arith.constant 20 : i32
+  !CHECK: %[[C20_I64:.*]] = fir.convert %[[C20]] : (i32) -> i64
+  !CHECK: %[[UB:.*]] = fir.convert %[[C20_I64]] : (i64) -> index
+  !CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
+  !CHECK: %[[SLICE:.*]] = fir.slice %[[LB]], %[[UB]], %[[STEP]] : (index, index, index) -> !fir.slice<1>
+  !CHECK: %[[ARR_SECTION:.*]] = fir.embox %[[DATA_COORD]](%[[SHAPE]]) [%[[SLICE]]] : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box<!fir.array<20xf32>>
+  !CHECK: %[[MEM:.*]] = fir.alloca !fir.box<!fir.array<20xf32>> 
+  !CHECK: fir.store %[[ARR_SECTION]] to %[[MEM]] : !fir.ref<!fir.box<!fir.array<20xf32>>> 
+  !CHECK: acc.data copy(%[[MEM]] : !fir.ref<!fir.box<!fir.array<20xf32>>>)
+
+end subroutine
+
+! Testing derived-type component without section
+subroutine acc_operand_derived_type_component()
+  type(wrapper) :: w
+
+  !$acc data copy(w%data)
+  !$acc end data
+
+  !CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_derived_type_component
+  !CHECK: %[[W:.*]] = fir.alloca !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>
+  !CHECK: %[[FIELD_INDEX:.*]] = fir.field_index data, !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>
+  !CHECK: %[[DATA_COORD:.*]] = fir.coordinate_of %[[W]], %[[FIELD_INDEX]] : (!fir.ref<!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>>, !fir.field) -> !fir.ref<!fir.array<100xf32>>
+  !CHECK: acc.data copy(%[[DATA_COORD]] : !fir.ref<!fir.array<100xf32>>) {
+
+end subroutine
+
+! Testing array of derived-type component without section
+subroutine acc_operand_array_derived_type_component()
+  type(wrapper) :: w(10)
+
+  !$acc data copy(w(1)%data)
+  !$acc end data
+
+  !CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_derived_type_component
+  !CHECK: %[[W:.*]] = fir.alloca !fir.array<10x!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>>
+  !CHECK: %[[IDX:.*]] = arith.subi %{{.*}}, %c1_i64 : i64
+  !CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[W]], %[[IDX]] : (!fir.ref<!fir.array<10x!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>>>, i64) -> !fir.ref<!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>>
+  !CHECK: %[[COORD2:.*]] = fir.field_index data, !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>
+  !CHECK: %[[COORD_OF:.*]] = fir.coordinate_of %[[COORD1]], %[[COORD2]] : (!fir.ref<!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>>, !fir.field) -> !fir.ref<!fir.array<100xf32>>
+  !CHECK: acc.data copy(%[[COORD_OF]] : !fir.ref<!fir.array<100xf32>>)
+
+end subroutine
+
+subroutine acc_operand_array_section2(a)
+  real, dimension(100) :: a
+
+  !$acc data copyin(a)
+  !$acc end data
+
+end subroutine
+
+end module

diff  --git a/flang/test/Semantics/OpenACC/acc-data.f90 b/flang/test/Semantics/OpenACC/acc-data.f90
index 24c67ee33494c..e51579ebb21c9 100644
--- a/flang/test/Semantics/OpenACC/acc-data.f90
+++ b/flang/test/Semantics/OpenACC/acc-data.f90
@@ -45,6 +45,12 @@ program openacc_data_validity
 
   !$acc enter data create(aa) if(.TRUE.)
 
+  !$acc enter data create(a(1:10))
+
+  !$acc enter data create(t%arr)
+
+  !$acc enter data create(t%arr(2:4))
+
   !ERROR: At most one IF clause can appear on the ENTER DATA directive
   !$acc enter data create(aa) if(.TRUE.) if(ifCondition)
 


        


More information about the flang-commits mailing list