[flang-commits] [flang] [llvm] [flang][openacc] Allow multiple clauses when in preceded by device_type (PR #73976)

Valentin Clement バレンタイン クレメン via flang-commits flang-commits at lists.llvm.org
Thu Nov 30 12:10:29 PST 2023


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

Some clauses can be repeated on the compute construct when they are placed after `device_type`. The semantic check was reporting an error for these cases. This patch fixes this.

>From 9714b10ff00d128e274c2170bdeea36751795759 Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Thu, 30 Nov 2023 11:47:04 -0800
Subject: [PATCH] [flang][openacc] Allow multiple clauses when in preceded by
 device_type

---
 flang/lib/Semantics/check-acc-structure.cpp   |  6 ++++
 .../lib/Semantics/check-directive-structure.h | 25 ++++++++++++++
 flang/test/Semantics/OpenACC/acc-parallel.f90 | 33 +++++++++++++++++++
 llvm/include/llvm/Frontend/OpenACC/ACC.td     | 12 +++----
 4 files changed, 70 insertions(+), 6 deletions(-)

diff --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp
index abda9409efd336b..932d5776a04680c 100644
--- a/flang/lib/Semantics/check-acc-structure.cpp
+++ b/flang/lib/Semantics/check-acc-structure.cpp
@@ -561,6 +561,8 @@ void AccStructureChecker::Enter(const parser::AccClause::NumGangs &n) {
       /*warnInsteadOfError=*/GetContext().directive ==
               llvm::acc::Directive::ACCD_serial ||
           GetContext().directive == llvm::acc::Directive::ACCD_serial_loop);
+  CheckAllowedOncePerGroup(
+      llvm::acc::Clause::ACCC_num_gangs, llvm::acc::Clause::ACCC_device_type);
 
   if (n.v.size() > 3)
     context_.Say(GetContext().clauseSource,
@@ -572,6 +574,8 @@ void AccStructureChecker::Enter(const parser::AccClause::NumWorkers &n) {
       /*warnInsteadOfError=*/GetContext().directive ==
               llvm::acc::Directive::ACCD_serial ||
           GetContext().directive == llvm::acc::Directive::ACCD_serial_loop);
+  CheckAllowedOncePerGroup(
+      llvm::acc::Clause::ACCC_num_workers, llvm::acc::Clause::ACCC_device_type);
 }
 
 void AccStructureChecker::Enter(const parser::AccClause::VectorLength &n) {
@@ -579,6 +583,8 @@ void AccStructureChecker::Enter(const parser::AccClause::VectorLength &n) {
       /*warnInsteadOfError=*/GetContext().directive ==
               llvm::acc::Directive::ACCD_serial ||
           GetContext().directive == llvm::acc::Directive::ACCD_serial_loop);
+  CheckAllowedOncePerGroup(llvm::acc::Clause::ACCC_vector_length,
+      llvm::acc::Clause::ACCC_device_type);
 }
 
 void AccStructureChecker::Enter(const parser::AccClause::Reduction &reduction) {
diff --git a/flang/lib/Semantics/check-directive-structure.h b/flang/lib/Semantics/check-directive-structure.h
index 84240b87f47ec4b..f7a6233a32edddb 100644
--- a/flang/lib/Semantics/check-directive-structure.h
+++ b/flang/lib/Semantics/check-directive-structure.h
@@ -349,6 +349,10 @@ class DirectiveStructureChecker : public virtual BaseChecker {
 
   void CheckAllowed(C clause, bool warnInsteadOfError = false);
 
+  // Check that the clause appears only once. The counter is reset when the
+  // separator clause appears.
+  void CheckAllowedOncePerGroup(C clause, C separator);
+
   void CheckAtLeastOneClause();
 
   void CheckNotAllowedIfClause(
@@ -545,6 +549,27 @@ void DirectiveStructureChecker<D, C, PC,
   }
 }
 
+template <typename D, typename C, typename PC, std::size_t ClauseEnumSize>
+void DirectiveStructureChecker<D, C, PC,
+    ClauseEnumSize>::CheckAllowedOncePerGroup(C clause, C separator) {
+  bool clauseIsPresent = false;
+  for (auto cl : GetContext().actualClauses) {
+    if (cl == clause) {
+      if (clauseIsPresent) {
+        context_.Say(GetContext().clauseSource,
+            "At most one %s clause can appear on the %s directive or in group separated by the %s clause"_err_en_US,
+            parser::ToUpperCaseLetters(getClauseName(clause).str()),
+            parser::ToUpperCaseLetters(GetContext().directiveSource.ToString()),
+            parser::ToUpperCaseLetters(getClauseName(separator).str()));
+      } else {
+        clauseIsPresent = true;
+      }
+    }
+    if (cl == separator)
+      clauseIsPresent = false;
+  }
+}
+
 // Check the value of the clause is a constant positive integer.
 template <typename D, typename C, typename PC, std::size_t ClauseEnumSize>
 void DirectiveStructureChecker<D, C, PC,
diff --git a/flang/test/Semantics/OpenACC/acc-parallel.f90 b/flang/test/Semantics/OpenACC/acc-parallel.f90
index c87d321593ddf3d..3f17d8fc862a678 100644
--- a/flang/test/Semantics/OpenACC/acc-parallel.f90
+++ b/flang/test/Semantics/OpenACC/acc-parallel.f90
@@ -155,4 +155,37 @@ program openacc_parallel_validity
   end do
   !$acc end parallel
 
+  !ERROR: At most one NUM_GANGS clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause
+  !$acc parallel num_gangs(400) num_gangs(400)
+  !$acc end parallel
+
+  !ERROR: At most one NUM_GANGS clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause
+  !$acc parallel device_type(nvidia) num_gangs(400) num_gangs(200)
+  !$acc end parallel
+
+  !$acc parallel device_type(nvidia) num_gangs(400) device_type(radeon) num_gangs(200)
+  !$acc end parallel
+
+  !ERROR: At most one NUM_WORKERS clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause
+  !$acc parallel num_workers(8) num_workers(4)
+  !$acc end parallel
+
+  !ERROR: At most one NUM_WORKERS clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause
+  !$acc parallel device_type(nvidia) num_workers(8) num_workers(4)
+  !$acc end parallel
+
+  !$acc parallel device_type(nvidia) num_workers(8) device_type(radeon) num_workers(4)
+  !$acc end parallel
+
+  !ERROR: At most one VECTOR_LENGTH clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause
+  !$acc parallel vector_length(128) vector_length(124)
+  !$acc end parallel
+
+  !ERROR: At most one VECTOR_LENGTH clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause
+  !$acc parallel device_type(nvidia) vector_length(256) vector_length(128)
+  !$acc end parallel
+
+  !$acc parallel device_type(nvidia) vector_length(256) device_type(radeon) vector_length(128)
+  !$acc end parallel
+
 end program openacc_parallel_validity
diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td
index 692ddefb1b4cc2e..013d18e160de461 100644
--- a/llvm/include/llvm/Frontend/OpenACC/ACC.td
+++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td
@@ -335,6 +335,7 @@ def ACC_Kernels : Directive<"kernels"> {
 def ACC_Parallel : Directive<"parallel"> {
   let allowedClauses = [
     VersionedClause<ACCC_Attach>,
+    VersionedClause<ACCC_Async>,
     VersionedClause<ACCC_Copy>,
     VersionedClause<ACCC_Copyin>,
     VersionedClause<ACCC_Copyout>,
@@ -342,20 +343,19 @@ def ACC_Parallel : Directive<"parallel"> {
     VersionedClause<ACCC_DevicePtr>,
     VersionedClause<ACCC_DeviceType>,
     VersionedClause<ACCC_NoCreate>,
+    VersionedClause<ACCC_NumGangs>,
+    VersionedClause<ACCC_NumWorkers>,
     VersionedClause<ACCC_Present>,
     VersionedClause<ACCC_Private>,
     VersionedClause<ACCC_FirstPrivate>,
     VersionedClause<ACCC_Reduction>,
-    VersionedClause<ACCC_Wait>
+    VersionedClause<ACCC_Wait>,
+    VersionedClause<ACCC_VectorLength>
   ];
   let allowedOnceClauses = [
-    VersionedClause<ACCC_Async>,
     VersionedClause<ACCC_Default>,
     VersionedClause<ACCC_If>,
-    VersionedClause<ACCC_NumGangs>,
-    VersionedClause<ACCC_NumWorkers>,
-    VersionedClause<ACCC_Self>,
-    VersionedClause<ACCC_VectorLength>
+    VersionedClause<ACCC_Self>
   ];
 }
 



More information about the flang-commits mailing list