diff options
author | Michael Kruse <llvm-project@meinersbur.de> | 2024-10-09 14:56:43 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-09 14:56:43 +0200 |
commit | 5b03efb85d63d1f4033ed649a56a177dd4ed62b4 (patch) | |
tree | 555389e7fb7e44a03f7c435350750c7aace3a609 /clang/lib/Sema/SemaOpenMP.cpp | |
parent | 32db6fbdb9a8173813e67606b87555c31ea557bb (diff) | |
download | llvm-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.cpp | 87 |
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); |