[flang-commits] [flang] [flang][openacc] Lower acc cache directive (PR #65673)

Valentin Clement バレンタイン クレメン via flang-commits flang-commits at lists.llvm.org
Thu Sep 7 14:02:35 PDT 2023


https://github.com/clementval created https://github.com/llvm/llvm-project/pull/65673:

The cache directive is attached directly to the acc.loop operation when the directive appears in the loop. When it appears before a loop, the OpenACCCacheConstruct is saved and attached when the acc.loop is created.

Depends on #65521 

>From e523fb1ebb79b1d955aba7f88142cb85b685bf26 Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Wed, 6 Sep 2023 15:04:05 -0700
Subject: [PATCH] [flang][openacc] Lower acc cache directive

---
 flang/include/flang/Lower/OpenACC.h   |  4 +-
 flang/lib/Lower/Bridge.cpp            |  5 +-
 flang/lib/Lower/OpenACC.cpp           | 66 ++++++++++++++++++++++++---
 flang/test/Lower/OpenACC/acc-loop.f90 | 52 +++++++++++++++++++++
 4 files changed, 118 insertions(+), 9 deletions(-)

diff --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h
index 447d5c43cad805..58b355fcdec81c 100644
--- a/flang/include/flang/Lower/OpenACC.h
+++ b/flang/include/flang/Lower/OpenACC.h
@@ -36,6 +36,7 @@ class FirOpBuilder;
 namespace Fortran {
 namespace parser {
 struct OpenACCConstruct;
+struct OpenACCCacheConstruct;
 struct OpenACCDeclarativeConstruct;
 } // namespace parser
 
@@ -65,7 +66,8 @@ static constexpr llvm::StringRef declarePostDeallocSuffix =
 
 void genOpenACCConstruct(AbstractConverter &,
                          Fortran::semantics::SemanticsContext &,
-                         pft::Evaluation &, const parser::OpenACCConstruct &);
+                         pft::Evaluation &, const parser::OpenACCConstruct &,
+                         llvm::SmallVector<const Fortran::parser::OpenACCCacheConstruct*>&);
 void genOpenACCDeclarativeConstruct(AbstractConverter &,
                                     Fortran::semantics::SemanticsContext &,
                                     StatementContext &, pft::Evaluation &,
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index d7dec54c76de5d..14f48c9d226676 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2285,7 +2285,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
   void genFIR(const Fortran::parser::OpenACCConstruct &acc) {
     mlir::OpBuilder::InsertPoint insertPt = builder->saveInsertionPoint();
-    genOpenACCConstruct(*this, bridge.getSemanticsContext(), getEval(), acc);
+    genOpenACCConstruct(*this, bridge.getSemanticsContext(), getEval(), acc, accCacheDirectives);
     for (Fortran::lower::pft::Evaluation &e : getEval().getNestedEvaluations())
       genFIR(e);
     builder->restoreInsertionPoint(insertPt);
@@ -4372,6 +4372,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     hostAssocTuple = mlir::Value{};
     localSymbols.clear();
     blockId = 0;
+    accCacheDirectives.clear();
   }
 
   /// Helper to generate GlobalOps when the builder is not positioned in any
@@ -4801,6 +4802,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
   /// Deferred OpenACC routine attachment.
   Fortran::lower::AccRoutineInfoMappingList accRoutineInfos;
+  /// Deferred OpenACC cache directive.
+  llvm::SmallVector<const Fortran::parser::OpenACCCacheConstruct*> accCacheDirectives;
 };
 
 } // namespace
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index d6f6ae18a40116..9652fe00dfd281 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -1500,10 +1500,36 @@ createLoopOp(Fortran::lower::AbstractConverter &converter,
   return loopOp;
 }
 
+static void
+attachCacheToLoop(Fortran::lower::AbstractConverter &converter,
+                  fir::FirOpBuilder &builder,
+                  Fortran::semantics::SemanticsContext &semanticsContext,
+                  const Fortran::parser::OpenACCCacheConstruct &cacheConstruct,
+                  mlir::acc::LoopOp &loopOp) {
+  Fortran::lower::StatementContext stmtCtx;
+  llvm::SmallVector<mlir::Value> cacheOperands;
+  const Fortran::parser::AccObjectListWithModifier &listWithModifier =
+        std::get<Fortran::parser::AccObjectListWithModifier>(cacheConstruct.t);
+  const auto &accObjectList =
+      std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+  const auto &modifier =
+      std::get<std::optional<Fortran::parser::AccDataModifier>>(listWithModifier.t);
+    
+  mlir::acc::DataClause dataClause = mlir::acc::DataClause::acc_cache;
+  if (modifier &&
+      (*modifier).v == Fortran::parser::AccDataModifier::Modifier::ReadOnly)
+    dataClause = mlir::acc::DataClause::acc_cache_readonly;
+  genDataOperandOperations<mlir::acc::CacheOp>(accObjectList, converter,
+      semanticsContext, stmtCtx, cacheOperands, dataClause,
+      /*structured=*/true, /*implicit=*/false, /*setDeclareAttr*/false);
+  loopOp.getCacheOperandsMutable().append(cacheOperands);
+}
+
 static void genACC(Fortran::lower::AbstractConverter &converter,
                    Fortran::semantics::SemanticsContext &semanticsContext,
                    Fortran::lower::pft::Evaluation &eval,
-                   const Fortran::parser::OpenACCLoopConstruct &loopConstruct) {
+                   const Fortran::parser::OpenACCLoopConstruct &loopConstruct,
+                   llvm::SmallVector<const Fortran::parser::OpenACCCacheConstruct*> &deferredCacheDirectives) {
 
   const auto &beginLoopDirective =
       std::get<Fortran::parser::AccBeginLoopDirective>(loopConstruct.t);
@@ -1517,8 +1543,17 @@ static void genACC(Fortran::lower::AbstractConverter &converter,
   if (loopDirective.v == llvm::acc::ACCD_loop) {
     const auto &accClauseList =
         std::get<Fortran::parser::AccClauseList>(beginLoopDirective.t);
-    createLoopOp(converter, currentLocation, semanticsContext, stmtCtx,
-                 accClauseList);
+    auto loopOp = createLoopOp(converter, currentLocation, semanticsContext,
+        stmtCtx, accClauseList);
+    if (!deferredCacheDirectives.empty()) {
+      fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+      auto crtPos = builder.saveInsertionPoint();
+      builder.setInsertionPoint(loopOp);
+      for (const Fortran::parser::OpenACCCacheConstruct* cacheCons : deferredCacheDirectives)
+        attachCacheToLoop(converter, builder, semanticsContext, *cacheCons, loopOp);
+      deferredCacheDirectives.clear();
+      builder.restoreInsertionPoint(crtPos);
+    }
   }
 }
 
@@ -3102,11 +3137,29 @@ void Fortran::lower::finalizeOpenACCRoutineAttachment(
   accRoutineInfos.clear();
 }
 
+static void
+genACC(Fortran::lower::AbstractConverter &converter,
+       Fortran::semantics::SemanticsContext &semanticsContext,
+       const Fortran::parser::OpenACCCacheConstruct &cacheConstruct,
+       llvm::SmallVector<const Fortran::parser::OpenACCCacheConstruct*> &deferredCacheDirectives) {
+  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  auto loopOp = builder.getRegion().getParentOfType<mlir::acc::LoopOp>();
+  auto crtPos = builder.saveInsertionPoint();
+  if (loopOp) {
+    builder.setInsertionPoint(loopOp);
+    attachCacheToLoop(converter, builder, semanticsContext, cacheConstruct, loopOp);
+  } else {
+    deferredCacheDirectives.push_back(&cacheConstruct);
+  }
+  builder.restoreInsertionPoint(crtPos);
+}
+
 void Fortran::lower::genOpenACCConstruct(
     Fortran::lower::AbstractConverter &converter,
     Fortran::semantics::SemanticsContext &semanticsContext,
     Fortran::lower::pft::Evaluation &eval,
-    const Fortran::parser::OpenACCConstruct &accConstruct) {
+    const Fortran::parser::OpenACCConstruct &accConstruct,
+    llvm::SmallVector<const Fortran::parser::OpenACCCacheConstruct*> &deferredCacheDirectives) {
 
   std::visit(
       common::visitors{
@@ -3118,15 +3171,14 @@ void Fortran::lower::genOpenACCConstruct(
             genACC(converter, semanticsContext, eval, combinedConstruct);
           },
           [&](const Fortran::parser::OpenACCLoopConstruct &loopConstruct) {
-            genACC(converter, semanticsContext, eval, loopConstruct);
+            genACC(converter, semanticsContext, eval, loopConstruct, deferredCacheDirectives);
           },
           [&](const Fortran::parser::OpenACCStandaloneConstruct
                   &standaloneConstruct) {
             genACC(converter, semanticsContext, eval, standaloneConstruct);
           },
           [&](const Fortran::parser::OpenACCCacheConstruct &cacheConstruct) {
-            TODO(converter.genLocation(cacheConstruct.source),
-                 "OpenACC Cache construct not lowered yet!");
+            genACC(converter, semanticsContext, cacheConstruct, deferredCacheDirectives);
           },
           [&](const Fortran::parser::OpenACCWaitConstruct &waitConstruct) {
             genACC(converter, eval, waitConstruct);
diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90
index eac4fa41af82a3..fd9d12cc18f34c 100644
--- a/flang/test/Lower/OpenACC/acc-loop.f90
+++ b/flang/test/Lower/OpenACC/acc-loop.f90
@@ -305,4 +305,56 @@ program acc_loop
 !CHECK:        acc.yield
 !CHECK-NEXT: }{{$}}
 
+  !$acc loop
+  DO i = 1, n
+    !$acc cache(b)
+    a(i) = b(i)
+  END DO
+
+! CHECK: %[[CACHE:.*]] = acc.cache varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"}
+! CHECK: acc.loop cache(%[[CACHE]] : !fir.ref<!fir.array<10xf32>>)
+
 end program
+
+
+subroutine sub1()
+  integer :: i
+  integer, parameter :: n = 10
+  real, dimension(n) :: a, b
+
+  !$acc cache(b)
+
+  !$acc loop
+  DO i = 1, n
+    a(i) = b(i)
+  END DO
+
+  !$acc loop
+  DO i = 1, n
+    a(i) = b(i)
+  END DO
+
+  !$acc cache(b)
+end subroutine
+
+! CHECK-LABEL: func.func @_QPsub1() {
+! CHECK: %[[CACHE:.*]] = acc.cache varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"}
+! CHECK: acc.loop cache(%[[CACHE]] : !fir.ref<!fir.array<10xf32>>)
+! CHECK: acc.loop {
+! CHECK-NOT: acc.cache
+
+subroutine sub2()
+  integer :: i
+  integer, parameter :: n = 10
+  real, dimension(n) :: a, b
+
+  !$acc loop
+  DO i = 1, n
+    !$acc cache(a)
+    a(i) = b(i)
+  END DO
+end subroutine
+
+! CHECK-LABEL: func.func @_QPsub2() {
+! CHECK: %[[CACHE:.*]] = acc.cache varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"}
+! CHECK: acc.loop cache(%[[CACHE]] : !fir.ref<!fir.array<10xf32>>)



More information about the flang-commits mailing list