r359132 - [OPENMP]Initial support for non-rectangular loop nest.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 24 12:58:30 PDT 2019


Author: abataev
Date: Wed Apr 24 12:58:30 2019
New Revision: 359132

URL: http://llvm.org/viewvc/llvm-project?rev=359132&view=rev
Log:
[OPENMP]Initial support for non-rectangular loop nest.

Added basic semantic analysis for the non-rectangular loop nests for
OpenMP 5.0 support.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/test/OpenMP/for_loop_messages.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=359132&r1=359131&r2=359132&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr 24 12:58:30 2019
@@ -9170,6 +9170,8 @@ def warn_omp_allocate_thread_on_task_tar
   InGroup<OpenMPClauses>;
 def err_omp_expected_private_copy_for_allocate : Error<
   "the referenced item is not found in any private clause on the same directive">;
+def err_omp_stmt_depends_on_loop_counter : Error<
+  "the loop %select{initializer|condition}0 expression depends on the current loop control variable">;
 } // end of OpenMP category
 
 let CategoryName = "Related Result Type Issue" in {

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=359132&r1=359131&r2=359132&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Apr 24 12:58:30 2019
@@ -4487,6 +4487,8 @@ namespace {
 class OpenMPIterationSpaceChecker {
   /// Reference to Sema.
   Sema &SemaRef;
+  /// Data-sharing stack.
+  DSAStackTy &Stack;
   /// A location for diagnostics (when there is no some better location).
   SourceLocation DefaultLoc;
   /// A location for diagnostics (when increment is not compatible).
@@ -4518,10 +4520,14 @@ class OpenMPIterationSpaceChecker {
   bool TestIsStrictOp = false;
   /// This flag is true when step is subtracted on each iteration.
   bool SubtractStep = false;
+  /// Checks if the provide statement depends on the loop counter.
+  bool doesDependOnLoopCounter(const Stmt *S, bool IsInitializer) const;
 
 public:
-  OpenMPIterationSpaceChecker(Sema &SemaRef, SourceLocation DefaultLoc)
-      : SemaRef(SemaRef), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
+  OpenMPIterationSpaceChecker(Sema &SemaRef, DSAStackTy &Stack,
+                              SourceLocation DefaultLoc)
+      : SemaRef(SemaRef), Stack(Stack), DefaultLoc(DefaultLoc),
+        ConditionLoc(DefaultLoc) {}
   /// Check init-expr for canonical loop form and save loop counter
   /// variable - #Var and its initialization value - #LB.
   bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
@@ -4579,7 +4585,8 @@ private:
   /// expression.
   bool checkAndSetIncRHS(Expr *RHS);
   /// Helper to set loop counter variable and its initializer.
-  bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB);
+  bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
+                      bool EmitDiags);
   /// Helper to set upper bound.
   bool setUB(Expr *NewUB, llvm::Optional<bool> LessOp, bool StrictOp,
              SourceRange SR, SourceLocation SL);
@@ -4599,7 +4606,7 @@ bool OpenMPIterationSpaceChecker::depend
 
 bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
                                                  Expr *NewLCRefExpr,
-                                                 Expr *NewLB) {
+                                                 Expr *NewLB, bool EmitDiags) {
   // State consistency checking to ensure correct usage.
   assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
          UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
@@ -4614,6 +4621,8 @@ bool OpenMPIterationSpaceChecker::setLCD
           CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
         NewLB = CE->getArg(0)->IgnoreParenImpCasts();
   LB = NewLB;
+  if (EmitDiags)
+    (void)doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
   return false;
 }
 
@@ -4632,6 +4641,7 @@ bool OpenMPIterationSpaceChecker::setUB(
   TestIsStrictOp = StrictOp;
   ConditionSrcRange = SR;
   ConditionLoc = SL;
+  (void)doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
   return false;
 }
 
@@ -4697,6 +4707,66 @@ bool OpenMPIterationSpaceChecker::setSte
   return false;
 }
 
+namespace {
+/// Checker for the non-rectangular loops. Checks if the initializer or
+/// condition expression references loop counter variable.
+class LoopCounterRefChecker final
+    : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
+  Sema &SemaRef;
+  DSAStackTy &Stack;
+  const ValueDecl *CurLCDecl = nullptr;
+  bool IsInitializer = true;
+
+public:
+  bool VisitDeclRefExpr(const DeclRefExpr *E) {
+    const ValueDecl *VD = E->getDecl();
+    if (isa<VarDecl>(VD)) {
+      if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
+        SemaRef.Diag(E->getExprLoc(),
+                     diag::err_omp_stmt_depends_on_loop_counter)
+            << (IsInitializer ? 0 : 1);
+        return false;
+      }
+      const auto &&Data = Stack.isLoopControlVariable(VD);
+      return Data.first;
+    }
+    return false;
+  }
+  bool VisitMemberExpr(const MemberExpr *E) {
+    if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
+      const ValueDecl *VD = E->getMemberDecl();
+      if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
+        SemaRef.Diag(E->getExprLoc(),
+                     diag::err_omp_stmt_depends_on_loop_counter)
+            << (IsInitializer ? 0 : 1);
+        return false;
+      }
+      const auto &&Data = Stack.isLoopControlVariable(VD);
+      return Data.first;
+    }
+    return false;
+  }
+  bool VisitStmt(const Stmt *S) {
+    for (const Stmt *Child : S->children()) {
+      if (Child && Visit(Child))
+        return true;
+    }
+    return false;
+  }
+  explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
+                                 const ValueDecl *CurLCDecl, bool IsInitializer)
+      : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
+        IsInitializer(IsInitializer) {}
+};
+} // namespace
+
+bool OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
+    const Stmt *S, bool IsInitializer) const {
+  // Check for the non-rectangular loops.
+  LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer);
+  return LoopStmtChecker.Visit(S);
+}
+
 bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
   // Check init-expr for canonical loop form and save loop counter
   // variable - #Var and its initialization value - #LB.
@@ -4725,13 +4795,15 @@ bool OpenMPIterationSpaceChecker::checkA
       if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
         if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
           if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
-            return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
-        return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS());
+            return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
+                                  EmitDiags);
+        return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
       }
       if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
         if (ME->isArrow() &&
             isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
-          return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+          return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
+                                EmitDiags);
       }
     }
   } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
@@ -4748,7 +4820,7 @@ bool OpenMPIterationSpaceChecker::checkA
               buildDeclRefExpr(SemaRef, Var,
                                Var->getType().getNonReferenceType(),
                                DS->getBeginLoc()),
-              Var->getInit());
+              Var->getInit(), EmitDiags);
         }
       }
     }
@@ -4758,13 +4830,15 @@ bool OpenMPIterationSpaceChecker::checkA
       if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
         if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
           if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
-            return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
-        return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1));
+            return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
+                                  EmitDiags);
+        return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
       }
       if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
         if (ME->isArrow() &&
             isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
-          return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+          return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
+                                EmitDiags);
       }
     }
   }
@@ -5261,7 +5335,7 @@ void Sema::ActOnOpenMPLoopInitialization
   if (AssociatedLoops > 0 &&
       isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
     DSAStack->loopStart();
-    OpenMPIterationSpaceChecker ISC(*this, ForLoc);
+    OpenMPIterationSpaceChecker ISC(*this, *DSAStack, ForLoc);
     if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
       if (ValueDecl *D = ISC.getLoopDecl()) {
         auto *VD = dyn_cast<VarDecl>(D);
@@ -5327,7 +5401,7 @@ static bool checkOpenMPIterationSpace(
   }
   assert(For->getBody());
 
-  OpenMPIterationSpaceChecker ISC(SemaRef, For->getForLoc());
+  OpenMPIterationSpaceChecker ISC(SemaRef, DSA, For->getForLoc());
 
   // Check init.
   Stmt *Init = For->getInit();

Modified: cfe/trunk/test/OpenMP/for_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_loop_messages.cpp?rev=359132&r1=359131&r2=359132&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_loop_messages.cpp Wed Apr 24 12:58:30 2019
@@ -287,6 +287,13 @@ int test_iteration_spaces() {
     c[ii] = a[ii];
 
 #pragma omp parallel
+// expected-error at +3 {{the loop initializer expression depends on the current loop control variable}}
+// expected-error at +2 2 {{the loop condition expression depends on the current loop control variable}}
+#pragma omp for
+  for (ii = ii * 10 + 25; ii < ii / ii - 23; ii += 1)
+    c[ii] = a[ii];
+
+#pragma omp parallel
 // expected-note at +2  {{defined as firstprivate}}
 // expected-error at +2 {{loop iteration variable in the associated loop of 'omp for' directive may not be firstprivate, predetermined as private}}
 #pragma omp for firstprivate(ii)
@@ -596,9 +603,17 @@ int test_with_random_access_iterator() {
 
 template <typename IT, int ST>
 class TC {
+  int ii;
 public:
   int dotest_lt(IT begin, IT end) {
 #pragma omp parallel
+// expected-error at +3 3 {{the loop initializer expression depends on the current loop control variable}}
+// expected-error at +2 6 {{the loop condition expression depends on the current loop control variable}}
+#pragma omp for
+  for (ii = ii * 10 + 25; ii < ii / ii - 23; ii += 1)
+    ;
+
+#pragma omp parallel
 // expected-note at +3 {{loop step is expected to be positive due to this condition}}
 // expected-error at +2 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
 #pragma omp for
@@ -659,7 +674,7 @@ void test_with_template() {
   GoodIter begin, end;
   TC<GoodIter, 100> t1;
   TC<GoodIter, -100> t2;
-  t1.dotest_lt(begin, end);
+  t1.dotest_lt(begin, end);         // expected-note {{in instantiation of member function 'TC<GoodIter, 100>::dotest_lt' requested here}}
   t2.dotest_lt(begin, end);         // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
   dotest_gt(begin, end);            // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
   dotest_gt<unsigned, 10>(0, 100);  // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, 10>' requested here}}




More information about the cfe-commits mailing list