[clang] loop bind : bug in checking Parent region (PR #76938)

via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 4 02:38:52 PST 2024


https://github.com/SunilKuravinakop created https://github.com/llvm/llvm-project/pull/76938

Changes uploaded to the phabricator on Dec 16th are lost because the phabricator is down. Hence re-uploading it to the github.com.

  Changes to be committed:
 	modified:   clang/include/clang/Sema/Sema.h
 	modified:   clang/lib/Sema/SemaOpenMP.cpp
 	modified:   clang/test/OpenMP/generic_loop_ast_print.cpp
 	modified:   clang/test/OpenMP/loop_bind_messages.cpp
 	modified:   clang/test/PCH/pragma-loop.cpp

>From 1dcd4703002acdde370a285089008e409043717b Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <kuravina at pe28vega.us.cray.com>
Date: Thu, 4 Jan 2024 04:08:28 -0600
Subject: [PATCH] Changes uploaded to the phabricator on Dec 16th are lost
 because the phabricator is down. Hence re-uploading it to the github.com.

  Changes to be committed:
 	modified:   clang/include/clang/Sema/Sema.h
 	modified:   clang/lib/Sema/SemaOpenMP.cpp
 	modified:   clang/test/OpenMP/generic_loop_ast_print.cpp
 	modified:   clang/test/OpenMP/loop_bind_messages.cpp
 	modified:   clang/test/PCH/pragma-loop.cpp
---
 clang/include/clang/Sema/Sema.h              |   8 +-
 clang/lib/Sema/SemaOpenMP.cpp                |  62 ++++---
 clang/test/OpenMP/generic_loop_ast_print.cpp |   4 +-
 clang/test/OpenMP/loop_bind_messages.cpp     | 180 +++++++++++++++++--
 clang/test/PCH/pragma-loop.cpp               |   8 +-
 5 files changed, 226 insertions(+), 36 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5e3b57ea33220b..3d8d94d200ac58 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11335,6 +11335,7 @@ class Sema final {
   /// on the parameter of the bind clause. In the methods for the
   /// mapped directives, check the parameters of the lastprivate clause.
   bool checkLastPrivateForMappedDirectives(ArrayRef<OMPClause *> Clauses);
+
   /// Depending on the bind clause of OMPD_loop map the directive to new
   /// directives.
   ///    1) loop bind(parallel) --> OMPD_for
@@ -11344,9 +11345,12 @@ class Sema final {
   /// rigorous semantic checking in the new mapped directives.
   bool mapLoopConstruct(llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
                         ArrayRef<OMPClause *> Clauses,
-                        OpenMPBindClauseKind BindKind,
+                        OpenMPBindClauseKind &BindKind,
                         OpenMPDirectiveKind &Kind,
-                        OpenMPDirectiveKind &PrevMappedDirective);
+                        OpenMPDirectiveKind &PrevMappedDirective,
+                        SourceLocation StartLoc, SourceLocation EndLoc,
+                        const DeclarationNameInfo &DirName,
+                        OpenMPDirectiveKind CancelRegion);
 
 public:
   /// The declarator \p D defines a function in the scope \p S which is nested
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index f34d2959dc6191..6e060e5b8ee268 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -5072,6 +5072,18 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
         CurrentRegion != OMPD_cancellation_point &&
         CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
       return false;
+    // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
+    // for a detailed explanation
+    if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
+        ((BindKind == OMPC_BIND_parallel) || (BindKind == OMPC_BIND_teams)) &&
+        (isOpenMPWorksharingDirective(ParentRegion) ||
+         ParentRegion == OMPD_loop)) {
+      int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
+      SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
+          << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
+          << getOpenMPDirectiveName(CurrentRegion);
+      return true;
+    }
     if (CurrentRegion == OMPD_cancellation_point ||
         CurrentRegion == OMPD_cancel) {
       // OpenMP [2.16, Nesting of Regions]
@@ -6124,35 +6136,36 @@ processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
 
 bool Sema::mapLoopConstruct(llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
                             ArrayRef<OMPClause *> Clauses,
-                            OpenMPBindClauseKind BindKind,
+                            OpenMPBindClauseKind &BindKind,
                             OpenMPDirectiveKind &Kind,
-                            OpenMPDirectiveKind &PrevMappedDirective) {
+                            OpenMPDirectiveKind &PrevMappedDirective,
+                            SourceLocation StartLoc, SourceLocation EndLoc,
+                            const DeclarationNameInfo &DirName,
+                            OpenMPDirectiveKind CancelRegion) {
 
   bool UseClausesWithoutBind = false;
 
   // Restricting to "#pragma omp loop bind"
   if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) {
+
+    const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
+
     if (BindKind == OMPC_BIND_unknown) {
       // Setting the enclosing teams or parallel construct for the loop
       // directive without bind clause.
       BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
 
-      const OpenMPDirectiveKind ParentDirective =
-          DSAStack->getParentDirective();
       if (ParentDirective == OMPD_unknown) {
         Diag(DSAStack->getDefaultDSALocation(),
              diag::err_omp_bind_required_on_loop);
       } else if (ParentDirective == OMPD_parallel ||
-                 ParentDirective == OMPD_target_parallel) {
+                 ParentDirective == OMPD_target_parallel)
         BindKind = OMPC_BIND_parallel;
-      } else if (ParentDirective == OMPD_teams ||
-                 ParentDirective == OMPD_target_teams) {
-        BindKind = OMPC_BIND_teams;
-      }
     } else {
-      // bind clause is present, so we should set flag indicating to only
-      // use the clauses that aren't the bind clause for the new directive that
-      // loop is lowered to.
+      // bind clause is present in loop directive. When the loop directive is
+      // changed to a new directive the bind clause is not used. So, we should
+      // set flag indicating to only use the clauses that aren't the
+      // bind clause.
       UseClausesWithoutBind = true;
     }
 
@@ -6213,26 +6226,35 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
     OpenMPDirectiveKind PrevMappedDirective) {
   StmtResult Res = StmtError();
   OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
+  llvm::SmallVector<OMPClause *> ClausesWithoutBind;
+  bool UseClausesWithoutBind = false;
+
   if (const OMPBindClause *BC =
           OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
     BindKind = BC->getBindKind();
+
+  // Variable used to note down the DirectiveKind because mapLoopConstruct may
+  // change "Kind" variable, due to mapping of "omp loop" to other directives.
+  OpenMPDirectiveKind DK = Kind;
+  if ((Kind == OMPD_loop) || (PrevMappedDirective == OMPD_loop)) {
+    UseClausesWithoutBind = mapLoopConstruct(
+        ClausesWithoutBind, Clauses, BindKind, Kind, PrevMappedDirective,
+        StartLoc, EndLoc, DirName, CancelRegion);
+    DK = OMPD_loop;
+  }
+
   // First check CancelRegion which is then used in checkNestingOfRegions.
   if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) ||
-      checkNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion,
-                            BindKind, StartLoc))
+      checkNestingOfRegions(*this, DSAStack, DK, DirName, CancelRegion,
+                            BindKind, StartLoc)) {
     return StmtError();
+  }
 
   // Report affected OpenMP target offloading behavior when in HIP lang-mode.
   if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) ||
                             isOpenMPTargetDataManagementDirective(Kind)))
     Diag(StartLoc, diag::warn_hip_omp_target_directives);
 
-  llvm::SmallVector<OMPClause *> ClausesWithoutBind;
-  bool UseClausesWithoutBind = false;
-
-  UseClausesWithoutBind = mapLoopConstruct(ClausesWithoutBind, Clauses,
-                                           BindKind, Kind, PrevMappedDirective);
-
   llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
   VarsWithInheritedDSAType VarsWithInheritedDSA;
   bool ErrorFound = false;
diff --git a/clang/test/OpenMP/generic_loop_ast_print.cpp b/clang/test/OpenMP/generic_loop_ast_print.cpp
index df806405571cf7..30ade214289188 100644
--- a/clang/test/OpenMP/generic_loop_ast_print.cpp
+++ b/clang/test/OpenMP/generic_loop_ast_print.cpp
@@ -95,11 +95,11 @@ void test() {
   }
 
   //PRINT: #pragma omp target teams
-  //PRINT: #pragma omp distribute
+  //PRINT: #pragma omp simd
   //DUMP: OMPTargetTeamsDirective
   //DUMP: CapturedStmt
   //DUMP: ForStmt
-  //DUMP: OMPDistributeDirective
+  //DUMP: OMPSimdDirective
   #pragma omp target teams
   for (int i=0; i<1000; ++i) {
     #pragma omp loop
diff --git a/clang/test/OpenMP/loop_bind_messages.cpp b/clang/test/OpenMP/loop_bind_messages.cpp
index f7fdf289714328..9492a29ba69498 100644
--- a/clang/test/OpenMP/loop_bind_messages.cpp
+++ b/clang/test/OpenMP/loop_bind_messages.cpp
@@ -4,6 +4,7 @@
 
 #define NNN 50
 int aaa[NNN];
+int aaa2[NNN][NNN];
 
 void parallel_loop() {
   #pragma omp parallel
@@ -15,6 +16,91 @@ void parallel_loop() {
    }
 }
 
+void parallel_for_AND_loop_bind() {
+  #pragma omp parallel for
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void parallel_nowait() {
+  #pragma omp parallel
+  #pragma omp for nowait
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void parallel_for_with_nothing() {
+  #pragma omp parallel for
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp nothing
+    #pragma omp loop
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void parallel_targetfor_with_loop_bind() {
+  #pragma omp target teams distribute parallel for
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void parallel_targetparallel_with_loop() {
+  #pragma omp target parallel
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(parallel)
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void loop_bind_AND_loop_bind() {
+  #pragma omp parallel for
+  for (int i = 0; i < 100; ++i) {
+    #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+    for (int i = 0 ; i < NNN ; i++) {
+      #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'loop' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+      for (int j = 0 ; j < NNN ; j++) {
+        aaa[j] = j*NNN;
+      }
+    }
+  }
+}
+
+void parallel_with_sections_loop() {
+  #pragma omp parallel
+  {
+     #pragma omp sections
+     {
+        for (int i = 0 ; i < NNN ; i++) {
+          #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+          for (int j = 0 ; j < NNN ; j++) {
+            aaa2[i][j] = i+j;
+          }
+        }
+
+        #pragma omp section
+	{
+          aaa[NNN-1] = NNN;
+        }
+     }
+  }
+}
+
 void teams_loop() {
   int var1, var2;
 
@@ -34,17 +120,23 @@ void teams_loop() {
    }
 }
 
-void orphan_loop_with_bind() {
-  #pragma omp loop bind(parallel) 
-  for (int j = 0 ; j < NNN ; j++) {
-    aaa[j] = j*NNN;
+void teams_targetteams_with_loop() {
+  #pragma omp target teams
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(teams)
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
   }
 }
 
-void orphan_loop_no_bind() {
-  #pragma omp loop  // expected-error{{expected 'bind' clause for 'loop' construct without an enclosing OpenMP construct}}
-  for (int j = 0 ; j < NNN ; j++) {
-    aaa[j] = j*NNN;
+void teams_targetfor_with_loop_bind() {
+  #pragma omp target teams distribute parallel for
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(teams) // expected-error{{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp loop' directive into a teams region?}}
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
   }
 }
 
@@ -65,12 +157,80 @@ void teams_loop_reduction() {
    }
 }
 
+void teams_loop_distribute() {
+  int total = 0;
+
+  #pragma omp teams num_teams(8) thread_limit(256)
+  #pragma omp distribute parallel for dist_schedule(static, 1024) \
+                                      schedule(static, 64)
+  for (int i = 0; i < NNN; i++) {
+    #pragma omp loop bind(teams) // expected-error{{'distribute parallel for' region; perhaps you forget to enclose 'omp loop' directive into a teams region?}}
+    for (int j = 0; j < NNN; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void parallel_for_with_loop_teams_bind(){
+  #pragma omp parallel for
+  for (int i = 0; i < NNN; i++) {
+    #pragma omp loop bind(teams) // expected-error{{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp loop' directive into a teams region?}}
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa[i] = i+i*NNN;
+    }
+  }
+}
+
+void teams_with_loop_thread_bind(){
+  #pragma omp teams
+  for (int i = 0; i < NNN; i++) {
+    #pragma omp loop bind(thread)
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa[i] = i+i*NNN;
+    }
+  }
+}
+
+void orphan_loop_no_bind() {
+  #pragma omp loop  // expected-error{{expected 'bind' clause for 'loop' construct without an enclosing OpenMP construct}}
+  for (int j = 0 ; j < NNN ; j++) {
+    aaa[j] = j*NNN;
+  }
+}
+
+void orphan_loop_parallel_bind() {
+  #pragma omp loop bind(parallel)
+  for (int j = 0 ; j < NNN ; j++) {
+    aaa[j] = j*NNN;
+  }
+}
+
+void orphan_loop_teams_bind(){
+  #pragma omp loop bind(teams)
+  for (int i = 0; i < NNN; i++) {
+    aaa[i] = i+i*NNN;
+  }
+}
+
 int main(int argc, char *argv[]) {
   parallel_loop();
+  parallel_for_AND_loop_bind();
+  parallel_nowait();
+  parallel_for_with_nothing();
+  parallel_targetfor_with_loop_bind();
+  parallel_targetparallel_with_loop();
+  loop_bind_AND_loop_bind();
+  parallel_with_sections_loop();
   teams_loop();
-  orphan_loop_with_bind();
-  orphan_loop_no_bind();
+  teams_targetteams_with_loop();
+  teams_targetfor_with_loop_bind();
   teams_loop_reduction();
+  teams_loop_distribute();
+  parallel_for_with_loop_teams_bind();
+  teams_with_loop_thread_bind();
+  orphan_loop_no_bind();
+  orphan_loop_parallel_bind();
+  orphan_loop_teams_bind();
 }
 
 #endif
diff --git a/clang/test/PCH/pragma-loop.cpp b/clang/test/PCH/pragma-loop.cpp
index f5de630ffc9120..a3c6871041c0ee 100644
--- a/clang/test/PCH/pragma-loop.cpp
+++ b/clang/test/PCH/pragma-loop.cpp
@@ -116,9 +116,13 @@ class pragma_test {
 
   inline void run10(int *List, int Length) {
     int i = 0;
-#pragma omp loop bind(teams)
+    int j = 0;
+    #pragma omp teams
     for (int i = 0; i < Length; i++) {
-      List[i] = i;
+      #pragma omp loop bind(teams)
+      for (int j = 0; j < Length; j++) {
+        List[i] = i+j;
+      }
     }
   }
 



More information about the cfe-commits mailing list