@@ -14956,7 +14956,9 @@ StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
1495614956 return StmtError();
1495714957
1495814958 // interchange without permutation clause swaps two loops.
14959- constexpr size_t NumLoops = 2;
14959+ const OMPPermutationClause *PermutationClause =
14960+ OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
14961+ size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
1496014962
1496114963 // Verify and diagnose loop nest.
1496214964 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
@@ -14971,6 +14973,12 @@ StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
1497114973 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
1497214974 NumLoops, AStmt, nullptr, nullptr);
1497314975
14976+ // An invalid expression in the permutation clause is set to nullptr in
14977+ // ActOnOpenMPPermutationClause.
14978+ if (PermutationClause &&
14979+ llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
14980+ return StmtError();
14981+
1497414982 assert(LoopHelpers.size() == NumLoops &&
1497514983 "Expecting loop iteration space dimensionaly to match number of "
1497614984 "affected loops");
@@ -14979,7 +14987,44 @@ StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
1497914987 "affected loops");
1498014988
1498114989 // Decode the permutation clause.
14982- constexpr uint64_t Permutation[] = {1, 0};
14990+ SmallVector<uint64_t, 2> Permutation;
14991+ if (!PermutationClause) {
14992+ Permutation = {1, 0};
14993+ } else {
14994+ ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
14995+ llvm::BitVector Flags(PermArgs.size());
14996+ for (Expr *PermArg : PermArgs) {
14997+ std::optional<llvm::APSInt> PermCstExpr =
14998+ PermArg->getIntegerConstantExpr(Context);
14999+ if (!PermCstExpr)
15000+ continue;
15001+ uint64_t PermInt = PermCstExpr->getZExtValue();
15002+ assert(1 <= PermInt && PermInt <= NumLoops &&
15003+ "Must be a permutation; diagnostic emitted in "
15004+ "ActOnOpenMPPermutationClause");
15005+ if (Flags[PermInt - 1]) {
15006+ SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15007+ Diag(PermArg->getExprLoc(),
15008+ diag::err_omp_interchange_permutation_value_repeated)
15009+ << PermInt << ExprRange;
15010+ continue;
15011+ }
15012+ Flags[PermInt - 1] = true;
15013+
15014+ Permutation.push_back(PermInt - 1);
15015+ }
15016+
15017+ if (Permutation.size() != NumLoops)
15018+ return StmtError();
15019+ }
15020+
15021+ // Nothing to transform with trivial permutation.
15022+ if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15023+ auto [Idx, Arg] = P;
15024+ return Idx == Arg;
15025+ }))
15026+ return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15027+ NumLoops, AStmt, AStmt, nullptr);
1498315028
1498415029 // Find the affected loops.
1498515030 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
@@ -16111,6 +16156,44 @@ OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
1611116156 SanitizedSizeExprs);
1611216157}
1611316158
16159+ OMPClause *SemaOpenMP::ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
16160+ SourceLocation StartLoc,
16161+ SourceLocation LParenLoc,
16162+ SourceLocation EndLoc) {
16163+ size_t NumLoops = PermExprs.size();
16164+ SmallVector<Expr *> SanitizedPermExprs;
16165+ llvm::append_range(SanitizedPermExprs, PermExprs);
16166+
16167+ for (Expr *&PermExpr : SanitizedPermExprs) {
16168+ // Skip if template-dependent or already sanitized, e.g. during a partial
16169+ // template instantiation.
16170+ if (!PermExpr || PermExpr->isInstantiationDependent())
16171+ continue;
16172+
16173+ llvm::APSInt PermVal;
16174+ ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
16175+ PermExpr, &PermVal, Sema::AllowFold);
16176+ bool IsValid = PermEvalExpr.isUsable();
16177+ if (IsValid)
16178+ PermExpr = PermEvalExpr.get();
16179+
16180+ if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16181+ SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
16182+ PermEvalExpr.get()->getEndLoc());
16183+ Diag(PermEvalExpr.get()->getExprLoc(),
16184+ diag::err_omp_interchange_permutation_value_range)
16185+ << NumLoops << ExprRange;
16186+ IsValid = false;
16187+ }
16188+
16189+ if (!PermExpr->isInstantiationDependent() && !IsValid)
16190+ PermExpr = nullptr;
16191+ }
16192+
16193+ return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
16194+ EndLoc, SanitizedPermExprs);
16195+ }
16196+
1611416197OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc,
1611516198 SourceLocation EndLoc) {
1611616199 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
0 commit comments