aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaOpenMP.cpp
diff options
context:
space:
mode:
authorMichael Kruse <llvm-project@meinersbur.de>2024-10-09 14:56:43 +0200
committerGitHub <noreply@github.com>2024-10-09 14:56:43 +0200
commit5b03efb85d63d1f4033ed649a56a177dd4ed62b4 (patch)
tree555389e7fb7e44a03f7c435350750c7aace3a609 /clang/lib/Sema/SemaOpenMP.cpp
parent32db6fbdb9a8173813e67606b87555c31ea557bb (diff)
downloadllvm-5b03efb85d63d1f4033ed649a56a177dd4ed62b4.zip
llvm-5b03efb85d63d1f4033ed649a56a177dd4ed62b4.tar.gz
llvm-5b03efb85d63d1f4033ed649a56a177dd4ed62b4.tar.bz2
[Clang][OpenMP] Add permutation clause (#92030)
Add the permutation clause for the interchange directive which will be introduced in the upcoming OpenMP 6.0 specification. A preview has been published in [Technical Report12](https://www.openmp.org/wp-content/uploads/openmp-TR12.pdf).
Diffstat (limited to 'clang/lib/Sema/SemaOpenMP.cpp')
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp87
1 files changed, 85 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 74ab521..d3e696a 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -14956,7 +14956,9 @@ StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
return StmtError();
// interchange without permutation clause swaps two loops.
- constexpr size_t NumLoops = 2;
+ const OMPPermutationClause *PermutationClause =
+ OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
+ size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
// Verify and diagnose loop nest.
SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
@@ -14971,6 +14973,12 @@ StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
NumLoops, AStmt, nullptr, nullptr);
+ // An invalid expression in the permutation clause is set to nullptr in
+ // ActOnOpenMPPermutationClause.
+ if (PermutationClause &&
+ llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
+ return StmtError();
+
assert(LoopHelpers.size() == NumLoops &&
"Expecting loop iteration space dimensionaly to match number of "
"affected loops");
@@ -14979,7 +14987,44 @@ StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
"affected loops");
// Decode the permutation clause.
- constexpr uint64_t Permutation[] = {1, 0};
+ SmallVector<uint64_t, 2> Permutation;
+ if (!PermutationClause) {
+ Permutation = {1, 0};
+ } else {
+ ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
+ llvm::BitVector Flags(PermArgs.size());
+ for (Expr *PermArg : PermArgs) {
+ std::optional<llvm::APSInt> PermCstExpr =
+ PermArg->getIntegerConstantExpr(Context);
+ if (!PermCstExpr)
+ continue;
+ uint64_t PermInt = PermCstExpr->getZExtValue();
+ assert(1 <= PermInt && PermInt <= NumLoops &&
+ "Must be a permutation; diagnostic emitted in "
+ "ActOnOpenMPPermutationClause");
+ if (Flags[PermInt - 1]) {
+ SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
+ Diag(PermArg->getExprLoc(),
+ diag::err_omp_interchange_permutation_value_repeated)
+ << PermInt << ExprRange;
+ continue;
+ }
+ Flags[PermInt - 1] = true;
+
+ Permutation.push_back(PermInt - 1);
+ }
+
+ if (Permutation.size() != NumLoops)
+ return StmtError();
+ }
+
+ // Nothing to transform with trivial permutation.
+ if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
+ auto [Idx, Arg] = P;
+ return Idx == Arg;
+ }))
+ return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ NumLoops, AStmt, AStmt, nullptr);
// Find the affected loops.
SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
@@ -16111,6 +16156,44 @@ OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
SanitizedSizeExprs);
}
+OMPClause *SemaOpenMP::ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ size_t NumLoops = PermExprs.size();
+ SmallVector<Expr *> SanitizedPermExprs;
+ llvm::append_range(SanitizedPermExprs, PermExprs);
+
+ for (Expr *&PermExpr : SanitizedPermExprs) {
+ // Skip if template-dependent or already sanitized, e.g. during a partial
+ // template instantiation.
+ if (!PermExpr || PermExpr->isInstantiationDependent())
+ continue;
+
+ llvm::APSInt PermVal;
+ ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
+ PermExpr, &PermVal, Sema::AllowFold);
+ bool IsValid = PermEvalExpr.isUsable();
+ if (IsValid)
+ PermExpr = PermEvalExpr.get();
+
+ if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
+ SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
+ PermEvalExpr.get()->getEndLoc());
+ Diag(PermEvalExpr.get()->getExprLoc(),
+ diag::err_omp_interchange_permutation_value_range)
+ << NumLoops << ExprRange;
+ IsValid = false;
+ }
+
+ if (!PermExpr->isInstantiationDependent() && !IsValid)
+ PermExpr = nullptr;
+ }
+
+ return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
+ EndLoc, SanitizedPermExprs);
+}
+
OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc,
SourceLocation EndLoc) {
return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);