[flang-commits] [flang] [flang] Allow acc cache directive inside acc routine (PR #184213)

via flang-commits flang-commits at lists.llvm.org
Mon Mar 2 11:52:53 PST 2026


https://github.com/khaki3 created https://github.com/llvm/llvm-project/pull/184213

While the spec allows the cache directive "at the top of (inside of) a loop", the directive has also been utilized at the top of an acc routine. This PR adds support for that.

>From b3caaa771b215c95c040eddf4ae4d26a0cfd8078 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Mon, 2 Mar 2026 11:44:19 -0800
Subject: [PATCH] [flang] Allow acc cache directive inside acc routine

Made-with: Cursor
---
 flang/lib/Semantics/check-acc-structure.cpp       |  7 ++++++-
 flang/lib/Semantics/check-acc-structure.h         |  1 +
 .../test/Semantics/OpenACC/acc-cache-validity.f90 | 15 +++++++++++++++
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp
index 24fdc7c048e5d..7a40b4f914c03 100644
--- a/flang/lib/Semantics/check-acc-structure.cpp
+++ b/flang/lib/Semantics/check-acc-structure.cpp
@@ -422,6 +422,7 @@ void AccStructureChecker::Enter(const parser::OpenACCRoutineConstruct &x) {
           "part of a subroutine or function definition, or within an interface "
           "body for a subroutine or function in an interface block"_err_en_US);
     }
+    hasAccRoutineDirective = true;
   }
 }
 void AccStructureChecker::Leave(const parser::OpenACCRoutineConstruct &) {
@@ -668,7 +669,7 @@ void AccStructureChecker::Enter(const parser::OpenACCCacheConstruct &x) {
   const auto &verbatim = std::get<parser::Verbatim>(x.t);
   PushContextAndClauseSets(verbatim.source, llvm::acc::Directive::ACCD_cache);
   SetContextDirectiveSource(verbatim.source);
-  if (loopNestLevel == 0) {
+  if (loopNestLevel == 0 && !hasAccRoutineDirective) {
     context_.Say(
         verbatim.source, "The CACHE directive must be inside a loop"_err_en_US);
   }
@@ -1155,18 +1156,22 @@ void AccStructureChecker::Enter(const parser::OpenACCEndConstruct &x) {
 
 void AccStructureChecker::Enter(const parser::Module &) {
   declareSymbols.clear();
+  hasAccRoutineDirective = false;
 }
 
 void AccStructureChecker::Enter(const parser::FunctionSubprogram &x) {
   declareSymbols.clear();
+  hasAccRoutineDirective = false;
 }
 
 void AccStructureChecker::Enter(const parser::SubroutineSubprogram &) {
   declareSymbols.clear();
+  hasAccRoutineDirective = false;
 }
 
 void AccStructureChecker::Enter(const parser::SeparateModuleSubprogram &) {
   declareSymbols.clear();
+  hasAccRoutineDirective = false;
 }
 
 void AccStructureChecker::Enter(const parser::DoConstruct &) {
diff --git a/flang/lib/Semantics/check-acc-structure.h b/flang/lib/Semantics/check-acc-structure.h
index 09399297ca4be..ffc7ce4263885 100644
--- a/flang/lib/Semantics/check-acc-structure.h
+++ b/flang/lib/Semantics/check-acc-structure.h
@@ -115,6 +115,7 @@ class AccStructureChecker
 
   llvm::SmallDenseMap<Symbol *, llvm::acc::Clause> declareSymbols;
   unsigned loopNestLevel = 0;
+  bool hasAccRoutineDirective = false;
 };
 
 } // namespace Fortran::semantics
diff --git a/flang/test/Semantics/OpenACC/acc-cache-validity.f90 b/flang/test/Semantics/OpenACC/acc-cache-validity.f90
index cef8fc041ae32..f0269b2460c90 100644
--- a/flang/test/Semantics/OpenACC/acc-cache-validity.f90
+++ b/flang/test/Semantics/OpenACC/acc-cache-validity.f90
@@ -55,4 +55,19 @@ program openacc_cache_validity
   !ERROR: The CACHE directive must be inside a loop
   !$acc cache(a)
 
+  call routine_with_cache()
+
+contains
+
+  subroutine routine_with_cache()
+    real(8), dimension(N) :: local_arr
+    integer :: j
+    !$acc routine vector
+    !$acc cache(local_arr)
+    !$acc loop
+    do j = 1, N
+      local_arr(j) = a(j)
+    end do
+  end subroutine
+
 end program openacc_cache_validity



More information about the flang-commits mailing list