[OPENMP] 'omp teams' directive basic support.
Includes parsing and semantic analysis for 'omp teams' directive support from OpenMP 4.0. Adds additional analysis to 'omp target' directive with 'omp teams' directive.  

llvm-svn: 219385
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 159f1bb..6e43a3d 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -92,15 +92,16 @@
     Scope *CurScope;
     SourceLocation ConstructLoc;
     bool OrderedRegion;
+    SourceLocation InnerTeamsRegionLoc;
     SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
                  Scope *CurScope, SourceLocation Loc)
         : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
           Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope),
-          ConstructLoc(Loc), OrderedRegion(false) {}
+          ConstructLoc(Loc), OrderedRegion(false), InnerTeamsRegionLoc() {}
     SharingMapTy()
         : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
           Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),
-          ConstructLoc(), OrderedRegion(false) {}
+          ConstructLoc(), OrderedRegion(false), InnerTeamsRegionLoc() {}
   };
 
   typedef SmallVector<SharingMapTy, 64> StackTy;
@@ -207,13 +208,30 @@
     return false;
   }
 
+  /// \brief Marks current target region as one with closely nested teams
+  /// region.
+  void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
+    if (Stack.size() > 2)
+      Stack[Stack.size() - 2].InnerTeamsRegionLoc = TeamsRegionLoc;
+  }
+  /// \brief Returns true, if current region has closely nested teams region.
+  bool hasInnerTeamsRegion() const {
+    return getInnerTeamsRegionLoc().isValid();
+  }
+  /// \brief Returns location of the nested teams region (if any).
+  SourceLocation getInnerTeamsRegionLoc() const {
+    if (Stack.size() > 1)
+      return Stack.back().InnerTeamsRegionLoc;
+    return SourceLocation();
+  }
+
   Scope *getCurScope() const { return Stack.back().CurScope; }
   Scope *getCurScope() { return Stack.back().CurScope; }
   SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
 };
 bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
   return isOpenMPParallelDirective(DKind) || DKind == OMPD_task ||
-         DKind == OMPD_unknown;
+         isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown;
 }
 } // namespace
 
@@ -276,7 +294,8 @@
     //  In a parallel construct, if no default clause is present, these
     //  variables are shared.
     DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
-    if (isOpenMPParallelDirective(DVar.DKind)) {
+    if (isOpenMPParallelDirective(DVar.DKind) ||
+        isOpenMPTeamsDirective(DVar.DKind)) {
       DVar.CKind = OMPC_shared;
       return DVar;
     }
@@ -933,7 +952,8 @@
       DVar = Stack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction),
                                     [](OpenMPDirectiveKind K) -> bool {
                                       return isOpenMPParallelDirective(K) ||
-                                             isOpenMPWorksharingDirective(K);
+                                             isOpenMPWorksharingDirective(K) ||
+                                             isOpenMPTeamsDirective(K);
                                     },
                                     false);
       if (DKind == OMPD_task && DVar.CKind == OMPC_reduction) {
@@ -1152,6 +1172,18 @@
                              Params);
     break;
   }
+  case OMPD_teams: {
+    QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+    QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+    Sema::CapturedParamNameType Params[] = {
+        std::make_pair(".global_tid.", KmpInt32PtrTy),
+        std::make_pair(".bound_tid.", KmpInt32PtrTy),
+        std::make_pair(StringRef(), QualType()) // __context with shared vars
+    };
+    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+                             Params);
+    break;
+  }
   case OMPD_threadprivate:
     llvm_unreachable("OpenMP Directive is not allowed");
   case OMPD_unknown:
@@ -1187,6 +1219,7 @@
   // | parallel         | ordered         | +                                  |
   // | parallel         | atomic          | *                                  |
   // | parallel         | target          | *                                  |
+  // | parallel         | teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   // | for              | parallel        | *                                  |
   // | for              | for             | +                                  |
@@ -1208,6 +1241,7 @@
   // | for              | ordered         | * (if construct is ordered)        |
   // | for              | atomic          | *                                  |
   // | for              | target          | *                                  |
+  // | for              | teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   // | master           | parallel        | *                                  |
   // | master           | for             | +                                  |
@@ -1229,6 +1263,7 @@
   // | master           | ordered         | +                                  |
   // | master           | atomic          | *                                  |
   // | master           | target          | *                                  |
+  // | master           | teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   // | critical         | parallel        | *                                  |
   // | critical         | for             | +                                  |
@@ -1249,6 +1284,7 @@
   // | critical         | ordered         | +                                  |
   // | critical         | atomic          | *                                  |
   // | critical         | target          | *                                  |
+  // | critical         | teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   // | simd             | parallel        |                                    |
   // | simd             | for             |                                    |
@@ -1270,6 +1306,7 @@
   // | simd             | ordered         |                                    |
   // | simd             | atomic          |                                    |
   // | simd             | target          |                                    |
+  // | simd             | teams           |                                    |
   // +------------------+-----------------+------------------------------------+
   // | for simd         | parallel        |                                    |
   // | for simd         | for             |                                    |
@@ -1291,6 +1328,7 @@
   // | for simd         | ordered         |                                    |
   // | for simd         | atomic          |                                    |
   // | for simd         | target          |                                    |
+  // | for simd         | teams           |                                    |
   // +------------------+-----------------+------------------------------------+
   // | parallel for simd| parallel        |                                    |
   // | parallel for simd| for             |                                    |
@@ -1312,6 +1350,7 @@
   // | parallel for simd| ordered         |                                    |
   // | parallel for simd| atomic          |                                    |
   // | parallel for simd| target          |                                    |
+  // | parallel for simd| teams           |                                    |
   // +------------------+-----------------+------------------------------------+
   // | sections         | parallel        | *                                  |
   // | sections         | for             | +                                  |
@@ -1333,6 +1372,7 @@
   // | sections         | ordered         | +                                  |
   // | sections         | atomic          | *                                  |
   // | sections         | target          | *                                  |
+  // | sections         | teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   // | section          | parallel        | *                                  |
   // | section          | for             | +                                  |
@@ -1354,6 +1394,7 @@
   // | section          | ordered         | +                                  |
   // | section          | atomic          | *                                  |
   // | section          | target          | *                                  |
+  // | section          | teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   // | single           | parallel        | *                                  |
   // | single           | for             | +                                  |
@@ -1375,6 +1416,7 @@
   // | single           | ordered         | +                                  |
   // | single           | atomic          | *                                  |
   // | single           | target          | *                                  |
+  // | single           | teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   // | parallel for     | parallel        | *                                  |
   // | parallel for     | for             | +                                  |
@@ -1396,6 +1438,7 @@
   // | parallel for     | ordered         | * (if construct is ordered)        |
   // | parallel for     | atomic          | *                                  |
   // | parallel for     | target          | *                                  |
+  // | parallel for     | teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   // | parallel sections| parallel        | *                                  |
   // | parallel sections| for             | +                                  |
@@ -1417,6 +1460,7 @@
   // | parallel sections| ordered         | +                                  |
   // | parallel sections| atomic          | *                                  |
   // | parallel sections| target          | *                                  |
+  // | parallel sections| teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   // | task             | parallel        | *                                  |
   // | task             | for             | +                                  |
@@ -1438,6 +1482,7 @@
   // | task             | ordered         | +                                  |
   // | task             | atomic          | *                                  |
   // | task             | target          | *                                  |
+  // | task             | teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   // | ordered          | parallel        | *                                  |
   // | ordered          | for             | +                                  |
@@ -1459,6 +1504,7 @@
   // | ordered          | ordered         | +                                  |
   // | ordered          | atomic          | *                                  |
   // | ordered          | target          | *                                  |
+  // | ordered          | teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   // | atomic           | parallel        |                                    |
   // | atomic           | for             |                                    |
@@ -1480,6 +1526,7 @@
   // | atomic           | ordered         |                                    |
   // | atomic           | atomic          |                                    |
   // | atomic           | target          |                                    |
+  // | atomic           | teams           |                                    |
   // +------------------+-----------------+------------------------------------+
   // | target           | parallel        | *                                  |
   // | target           | for             | *                                  |
@@ -1501,6 +1548,29 @@
   // | target           | ordered         | *                                  |
   // | target           | atomic          | *                                  |
   // | target           | target          | *                                  |
+  // | target           | teams           | *                                  |
+  // +------------------+-----------------+------------------------------------+
+  // | teams            | parallel        | *                                  |
+  // | teams            | for             | +                                  |
+  // | teams            | for simd        | +                                  |
+  // | teams            | master          | +                                  |
+  // | teams            | critical        | +                                  |
+  // | teams            | simd            | +                                  |
+  // | teams            | sections        | +                                  |
+  // | teams            | section         | +                                  |
+  // | teams            | single          | +                                  |
+  // | teams            | parallel for    | *                                  |
+  // | teams            |parallel for simd| *                                  |
+  // | teams            |parallel sections| *                                  |
+  // | teams            | task            | +                                  |
+  // | teams            | taskyield       | +                                  |
+  // | teams            | barrier         | +                                  |
+  // | teams            | taskwait        | +                                  |
+  // | teams            | flush           | +                                  |
+  // | teams            | ordered         | +                                  |
+  // | teams            | atomic          | +                                  |
+  // | teams            | target          | +                                  |
+  // | teams            | teams           | +                                  |
   // +------------------+-----------------+------------------------------------+
   if (Stack->getCurScope()) {
     auto ParentRegion = Stack->getParentDirective();
@@ -1509,7 +1579,8 @@
     enum {
       NoRecommend,
       ShouldBeInParallelRegion,
-      ShouldBeInOrderedRegion
+      ShouldBeInOrderedRegion,
+      ShouldBeInTargetRegion
     } Recommend = NoRecommend;
     if (isOpenMPSimdDirective(ParentRegion)) {
       // OpenMP [2.16, Nesting of Regions]
@@ -1604,6 +1675,22 @@
                           ParentRegion == OMPD_task ||
                           !Stack->isParentOrderedRegion();
       Recommend = ShouldBeInOrderedRegion;
+    } else if (isOpenMPTeamsDirective(CurrentRegion)) {
+      // OpenMP [2.16, Nesting of Regions]
+      // If specified, a teams construct must be contained within a target
+      // construct.
+      NestingProhibited = ParentRegion != OMPD_target;
+      Recommend = ShouldBeInTargetRegion;
+      Stack->setParentTeamsRegionLoc(Stack->getConstructLoc());
+    }
+    if (!NestingProhibited && isOpenMPTeamsDirective(ParentRegion)) {
+      // OpenMP [2.16, Nesting of Regions]
+      // distribute, parallel, parallel sections, parallel workshare, and the
+      // parallel loop and parallel loop SIMD constructs are the only OpenMP
+      // constructs that can be closely nested in the teams region.
+      // TODO: add distribute directive.
+      NestingProhibited = !isOpenMPParallelDirective(CurrentRegion);
+      Recommend = ShouldBeInParallelRegion;
     }
     if (NestingProhibited) {
       SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
@@ -1743,6 +1830,10 @@
     Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
                                      EndLoc);
     break;
+  case OMPD_teams:
+    Res =
+        ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
+    break;
   case OMPD_target:
     Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
                                      EndLoc);
@@ -3161,11 +3252,58 @@
                                             SourceLocation EndLoc) {
   assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
 
+  // OpenMP [2.16, Nesting of Regions]
+  // If specified, a teams construct must be contained within a target
+  // construct. That target construct must contain no statements or directives
+  // outside of the teams construct.
+  if (DSAStack->hasInnerTeamsRegion()) {
+    auto S = AStmt->IgnoreContainers(/*IgnoreCaptured*/ true);
+    bool OMPTeamsFound = true;
+    if (auto *CS = dyn_cast<CompoundStmt>(S)) {
+      auto I = CS->body_begin();
+      while (I != CS->body_end()) {
+        auto OED = dyn_cast<OMPExecutableDirective>(*I);
+        if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind())) {
+          OMPTeamsFound = false;
+          break;
+        }
+        ++I;
+      }
+      assert(I != CS->body_end() && "Not found statement");
+      S = *I;
+    }
+    if (!OMPTeamsFound) {
+      Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
+      Diag(DSAStack->getInnerTeamsRegionLoc(),
+           diag::note_omp_nested_teams_construct_here);
+      Diag(S->getLocStart(), diag::note_omp_nested_statement_here)
+          << isa<OMPExecutableDirective>(S);
+      return StmtError();
+    }
+  }
+
   getCurFunction()->setHasBranchProtectedScope();
 
   return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
 }
 
+StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
+                                           Stmt *AStmt, SourceLocation StartLoc,
+                                           SourceLocation EndLoc) {
+  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+  CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+  // 1.2.2 OpenMP Language Terminology
+  // Structured block - An executable statement with a single entry at the
+  // top and a single exit at the bottom.
+  // The point of exit cannot be a branch out of the structured block.
+  // longjmp() and throw() must not violate the entry/exit criteria.
+  CS->getCapturedDecl()->setNothrow();
+
+  getCurFunction()->setHasBranchProtectedScope();
+
+  return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
+}
+
 OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
                                              SourceLocation StartLoc,
                                              SourceLocation LParenLoc,