aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaOpenMP.cpp
diff options
context:
space:
mode:
authorChi Chun Chen <chichun.chen@hpe.com>2023-08-09 14:26:29 -0500
committerChi Chun Chen <chichun.chen@hpe.com>2023-08-09 14:26:38 -0500
commit8ab62da18d47fa0ce6aef9da50cca34a26ea775c (patch)
tree342eadf496c76a44bd16d5770a0dcc5f40a4965e /clang/lib/Sema/SemaOpenMP.cpp
parent15a08cf27cd48071ab32fcac584419e1dc2174c1 (diff)
downloadllvm-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.cpp177
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(