diff options
Diffstat (limited to 'clang/lib/Sema/SemaOpenMP.cpp')
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 150 |
1 files changed, 144 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 159f1bb08ed..6e43a3d4b26 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -92,15 +92,16 @@ private: 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 @@ public: 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 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter, // 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 @@ public: 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 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { 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 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel | ordered | + | // | parallel | atomic | * | // | parallel | target | * | + // | parallel | teams | + | // +------------------+-----------------+------------------------------------+ // | for | parallel | * | // | for | for | + | @@ -1208,6 +1241,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for | ordered | * (if construct is ordered) | // | for | atomic | * | // | for | target | * | + // | for | teams | + | // +------------------+-----------------+------------------------------------+ // | master | parallel | * | // | master | for | + | @@ -1229,6 +1263,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | master | ordered | + | // | master | atomic | * | // | master | target | * | + // | master | teams | + | // +------------------+-----------------+------------------------------------+ // | critical | parallel | * | // | critical | for | + | @@ -1249,6 +1284,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | critical | ordered | + | // | critical | atomic | * | // | critical | target | * | + // | critical | teams | + | // +------------------+-----------------+------------------------------------+ // | simd | parallel | | // | simd | for | | @@ -1270,6 +1306,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | simd | ordered | | // | simd | atomic | | // | simd | target | | + // | simd | teams | | // +------------------+-----------------+------------------------------------+ // | for simd | parallel | | // | for simd | for | | @@ -1291,6 +1328,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for simd | ordered | | // | for simd | atomic | | // | for simd | target | | + // | for simd | teams | | // +------------------+-----------------+------------------------------------+ // | parallel for simd| parallel | | // | parallel for simd| for | | @@ -1312,6 +1350,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for simd| ordered | | // | parallel for simd| atomic | | // | parallel for simd| target | | + // | parallel for simd| teams | | // +------------------+-----------------+------------------------------------+ // | sections | parallel | * | // | sections | for | + | @@ -1333,6 +1372,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | sections | ordered | + | // | sections | atomic | * | // | sections | target | * | + // | sections | teams | + | // +------------------+-----------------+------------------------------------+ // | section | parallel | * | // | section | for | + | @@ -1354,6 +1394,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | section | ordered | + | // | section | atomic | * | // | section | target | * | + // | section | teams | + | // +------------------+-----------------+------------------------------------+ // | single | parallel | * | // | single | for | + | @@ -1375,6 +1416,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | single | ordered | + | // | single | atomic | * | // | single | target | * | + // | single | teams | + | // +------------------+-----------------+------------------------------------+ // | parallel for | parallel | * | // | parallel for | for | + | @@ -1396,6 +1438,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | 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 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel sections| ordered | + | // | parallel sections| atomic | * | // | parallel sections| target | * | + // | parallel sections| teams | + | // +------------------+-----------------+------------------------------------+ // | task | parallel | * | // | task | for | + | @@ -1438,6 +1482,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | task | ordered | + | // | task | atomic | * | // | task | target | * | + // | task | teams | + | // +------------------+-----------------+------------------------------------+ // | ordered | parallel | * | // | ordered | for | + | @@ -1459,6 +1504,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | ordered | ordered | + | // | ordered | atomic | * | // | ordered | target | * | + // | ordered | teams | + | // +------------------+-----------------+------------------------------------+ // | atomic | parallel | | // | atomic | for | | @@ -1480,6 +1526,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | atomic | ordered | | // | atomic | atomic | | // | atomic | target | | + // | atomic | teams | | // +------------------+-----------------+------------------------------------+ // | target | parallel | * | // | target | for | * | @@ -1501,6 +1548,29 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | 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 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, enum { NoRecommend, ShouldBeInParallelRegion, - ShouldBeInOrderedRegion + ShouldBeInOrderedRegion, + ShouldBeInTargetRegion } Recommend = NoRecommend; if (isOpenMPSimdDirective(ParentRegion)) { // OpenMP [2.16, Nesting of Regions] @@ -1604,6 +1675,22 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, 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 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, 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 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses, 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, |