diff options
author | Chi Chun Chen <chichun.chen@hpe.com> | 2023-08-09 14:26:29 -0500 |
---|---|---|
committer | Chi Chun Chen <chichun.chen@hpe.com> | 2023-08-09 14:26:38 -0500 |
commit | 8ab62da18d47fa0ce6aef9da50cca34a26ea775c (patch) | |
tree | 342eadf496c76a44bd16d5770a0dcc5f40a4965e /clang/lib/Sema/SemaOpenMP.cpp | |
parent | 15a08cf27cd48071ab32fcac584419e1dc2174c1 (diff) | |
download | llvm-8ab62da18d47fa0ce6aef9da50cca34a26ea775c.zip llvm-8ab62da18d47fa0ce6aef9da50cca34a26ea775c.tar.gz llvm-8ab62da18d47fa0ce6aef9da50cca34a26ea775c.tar.bz2 |
[Clang][OpenMP] Support for Code Generation of loop bind clause
Support for Code Generation of "#pragma loop bind" clause.
1) bind(parallel)
2) bind(teams)
3) bind(thread)
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D144634
Diffstat (limited to 'clang/lib/Sema/SemaOpenMP.cpp')
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 177 |
1 files changed, 166 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 6787c6c..404b215 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -163,6 +163,10 @@ private: SourceLocation DefaultAttrLoc; DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown]; OpenMPDirectiveKind Directive = OMPD_unknown; + /// GenericLoopDirective with bind clause is mapped to other directives, + /// like for, distribute and simd. Presently, set MappedDirective to + /// OMPLoop. This may also be used in a similar way for other constructs. + OpenMPDirectiveKind MappedDirective = OMPD_unknown; DeclarationNameInfo DirectiveName; Scope *CurScope = nullptr; DeclContext *Context = nullptr; @@ -636,6 +640,24 @@ public: const SharingMapTy *Top = getTopOfStackOrNull(); return Top ? Top->Directive : OMPD_unknown; } + OpenMPDirectiveKind getMappedDirective() const { + const SharingMapTy *Top = getTopOfStackOrNull(); + return Top ? Top->MappedDirective : OMPD_unknown; + } + void setCurrentDirective(OpenMPDirectiveKind NewDK) { + SharingMapTy *Top = getTopOfStackOrNull(); + assert(Top && + "Before calling setCurrentDirective Top of Stack not to be NULL."); + // Store the old into MappedDirective & assign argument NewDK to Directive. + Top->Directive = NewDK; + } + void setMappedDirective(OpenMPDirectiveKind NewDK) { + SharingMapTy *Top = getTopOfStackOrNull(); + assert(Top && + "Before calling setMappedDirective Top of Stack not to be NULL."); + // Store the old into MappedDirective & assign argument NewDK to Directive. + Top->MappedDirective = NewDK; + } /// Returns directive kind at specified level. OpenMPDirectiveKind getDirective(unsigned Level) const { assert(!isStackEmpty() && "No directive at specified level."); @@ -5679,7 +5701,8 @@ static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy, // the step size, rounding-up the effective upper bound ensures that the // last iteration is included. // Note that the rounding-up may cause an overflow in a temporry that - // could be avoided, but would have occurred in a C-style for-loop as well. + // could be avoided, but would have occurred in a C-style for-loop as + // well. Expr *Divisor = BuildVarRef(NewStep); if (Rel == BO_GE || Rel == BO_GT) Divisor = @@ -6086,10 +6109,95 @@ processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, } } +bool Sema::mapLoopConstruct(llvm::SmallVector<OMPClause *> &ClausesWithoutBind, + ArrayRef<OMPClause *> Clauses, + OpenMPBindClauseKind BindKind, + OpenMPDirectiveKind &Kind, + OpenMPDirectiveKind &PrevMappedDirective) { + + bool UseClausesWithoutBind = false; + + // Restricting to "#pragma omp loop bind" + if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) { + 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) { + 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. + UseClausesWithoutBind = true; + } + + for (OMPClause *C : Clauses) { + // Spec restriction : bind(teams) and reduction not permitted. + if (BindKind == OMPC_BIND_teams && + C->getClauseKind() == llvm::omp::Clause::OMPC_reduction) + Diag(DSAStack->getDefaultDSALocation(), + diag::err_omp_loop_reduction_clause); + + // A new Vector ClausesWithoutBind, which does not contain the bind + // clause, for passing to new directive. + if (C->getClauseKind() != llvm::omp::Clause::OMPC_bind) + ClausesWithoutBind.push_back(C); + } + + switch (BindKind) { + case OMPC_BIND_parallel: + Kind = OMPD_for; + DSAStack->setCurrentDirective(OMPD_for); + DSAStack->setMappedDirective(OMPD_loop); + PrevMappedDirective = OMPD_loop; + break; + case OMPC_BIND_teams: + Kind = OMPD_distribute; + DSAStack->setCurrentDirective(OMPD_distribute); + DSAStack->setMappedDirective(OMPD_loop); + PrevMappedDirective = OMPD_loop; + break; + case OMPC_BIND_thread: + Kind = OMPD_simd; + DSAStack->setCurrentDirective(OMPD_simd); + DSAStack->setMappedDirective(OMPD_loop); + PrevMappedDirective = OMPD_loop; + break; + case OMPC_BIND_unknown: + break; + } + } else if (PrevMappedDirective == OMPD_loop) { + /// An initial pass after recognizing all the statements is done in the + /// Parser when the directive OMPD_loop is mapped to OMPD_for, + /// OMPD_distribute or OMPD_simd. A second transform pass with call from + /// clang::TreeTransform::TransformOMPExecutableDirective() is done + /// with the Directive as one of the above mapped directive without + /// the bind clause. Then "PrevMappedDirective" stored in the + /// OMPExecutableDirective is accessed and hence this else statement. + + DSAStack->setMappedDirective(OMPD_loop); + } + + return UseClausesWithoutBind; +} + StmtResult Sema::ActOnOpenMPExecutableDirective( OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses, - Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { + Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, + OpenMPDirectiveKind PrevMappedDirective) { StmtResult Res = StmtError(); OpenMPBindClauseKind BindKind = OMPC_BIND_unknown; if (const OMPBindClause *BC = @@ -6106,10 +6214,21 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( 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; - ClausesWithImplicit.append(Clauses.begin(), Clauses.end()); + if (getLangOpts().OpenMP >= 50 && UseClausesWithoutBind) { + ClausesWithImplicit.append(ClausesWithoutBind.begin(), + ClausesWithoutBind.end()); + } else { + ClausesWithImplicit.append(Clauses.begin(), Clauses.end()); + } if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic && Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master && Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) { @@ -9203,9 +9322,13 @@ static bool checkOpenMPIterationSpace( auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S); // Ranged for is supported only in OpenMP 5.0. if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) { + OpenMPDirectiveKind DK = (SemaRef.getLangOpts().OpenMP < 50 || + DSA.getMappedDirective() == OMPD_unknown) + ? DKind + : DSA.getMappedDirective(); SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for) << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr) - << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount + << getOpenMPDirectiveName(DK) << TotalNestedLoopCount << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount; if (TotalNestedLoopCount > 1) { if (CollapseLoopCountExpr && OrderedLoopCountExpr) @@ -10320,6 +10443,24 @@ static bool checkSimdlenSafelenSpecified(Sema &S, return false; } +static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses, + OpenMPDirectiveKind K, + DSAStackTy *Stack); + +bool Sema::checkLastPrivateForMappedDirectives(ArrayRef<OMPClause *> Clauses) { + + // Check for syntax of lastprivate + // Param of the lastprivate have different meanings in the mapped directives + // e.g. "omp loop" Only loop iteration vars are allowed in lastprivate clause + // "omp for" lastprivate vars must be shared + if (getLangOpts().OpenMP >= 50 && + DSAStack->getMappedDirective() == OMPD_loop && + checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack)) { + return false; + } + return true; +} + StmtResult Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, @@ -10327,6 +10468,9 @@ Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, if (!AStmt) return StmtError(); + if (!checkLastPrivateForMappedDirectives(Clauses)) + return StmtError(); + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); OMPLoopBasedDirective::HelperExprs B; // In presence of clause 'collapse' or 'ordered' with number of loops, it will @@ -10355,8 +10499,10 @@ Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, return StmtError(); setFunctionHasBranchProtectedScope(); - return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, - Clauses, AStmt, B); + auto *SimdDirective = OMPSimdDirective::Create( + Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, + DSAStack->getMappedDirective()); + return SimdDirective; } StmtResult @@ -10366,6 +10512,9 @@ Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, if (!AStmt) return StmtError(); + if (!checkLastPrivateForMappedDirectives(Clauses)) + return StmtError(); + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); OMPLoopBasedDirective::HelperExprs B; // In presence of clause 'collapse' or 'ordered' with number of loops, it will @@ -10390,10 +10539,11 @@ Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, } } - setFunctionHasBranchProtectedScope(); - return OMPForDirective::Create( + auto *ForDirective = OMPForDirective::Create( Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, - DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); + DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion(), + DSAStack->getMappedDirective()); + return ForDirective; } StmtResult Sema::ActOnOpenMPForSimdDirective( @@ -13940,6 +14090,9 @@ StmtResult Sema::ActOnOpenMPDistributeDirective( if (!AStmt) return StmtError(); + if (!checkLastPrivateForMappedDirectives(Clauses)) + return StmtError(); + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); OMPLoopBasedDirective::HelperExprs B; // In presence of clause 'collapse' with number of loops, it will @@ -13955,8 +14108,10 @@ StmtResult Sema::ActOnOpenMPDistributeDirective( "omp for loop exprs were not built"); setFunctionHasBranchProtectedScope(); - return OMPDistributeDirective::Create(Context, StartLoc, EndLoc, - NestedLoopCount, Clauses, AStmt, B); + auto *DistributeDirective = OMPDistributeDirective::Create( + Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, + DSAStack->getMappedDirective()); + return DistributeDirective; } StmtResult Sema::ActOnOpenMPDistributeParallelForDirective( |