[llvm-branch-commits] [clang] [flang] [llvm] [openmp] [Clang][OpenMP] Add reverse and interchange directives (PR #92030)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon May 13 23:50:22 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Michael Kruse (Meinersbur)
<details>
<summary>Changes</summary>
Add the reverse and interchange directives which will be introduced in the upcoming OpenMP 6.0 specification. A preview has been published in [Technical Report 12](https://www.openmp.org/wp-content/uploads/openmp-TR12.pdf).
The boilerplate code of the new directives largely overlaps. Having both in a single PR should be easier to review and avoids confects when inevitably one is committed before the other.
---
Patch is 561.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/92030.diff
47 Files Affected:
- (modified) clang/include/clang-c/Index.h (+8)
- (modified) clang/include/clang/AST/OpenMPClause.h (+100)
- (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+14)
- (modified) clang/include/clang/AST/StmtOpenMP.h (+144-2)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4)
- (modified) clang/include/clang/Basic/StmtNodes.td (+2)
- (modified) clang/include/clang/Parse/Parser.h (+3)
- (modified) clang/include/clang/Sema/SemaOpenMP.h (+16)
- (modified) clang/include/clang/Serialization/ASTBitCodes.h (+2)
- (modified) clang/lib/AST/OpenMPClause.cpp (+31)
- (modified) clang/lib/AST/StmtOpenMP.cpp (+39)
- (modified) clang/lib/AST/StmtPrinter.cpp (+10)
- (modified) clang/lib/AST/StmtProfile.cpp (+16)
- (modified) clang/lib/Basic/OpenMPKinds.cpp (+6-1)
- (modified) clang/lib/CodeGen/CGStmt.cpp (+6)
- (modified) clang/lib/CodeGen/CGStmtOpenMP.cpp (+18)
- (modified) clang/lib/CodeGen/CodeGenFunction.h (+2)
- (modified) clang/lib/Parse/ParseOpenMP.cpp (+24)
- (modified) clang/lib/Sema/SemaExceptionSpec.cpp (+2)
- (modified) clang/lib/Sema/SemaOpenMP.cpp (+435)
- (modified) clang/lib/Sema/TreeTransform.h (+57)
- (modified) clang/lib/Serialization/ASTReader.cpp (+11)
- (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+23)
- (modified) clang/lib/Serialization/ASTWriter.cpp (+7)
- (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+10)
- (added) clang/test/OpenMP/interchange_ast_print.cpp (+233)
- (added) clang/test/OpenMP/interchange_codegen.cpp (+5323)
- (added) clang/test/OpenMP/interchange_messages.cpp (+231)
- (added) clang/test/OpenMP/reverse_ast_print.cpp (+159)
- (added) clang/test/OpenMP/reverse_codegen.cpp (+1554)
- (added) clang/test/OpenMP/reverse_messages.cpp (+40)
- (modified) clang/tools/libclang/CIndex.cpp (+21)
- (modified) clang/tools/libclang/CXCursor.cpp (+6)
- (modified) flang/lib/Lower/OpenMP/Clauses.cpp (+6)
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+1)
- (modified) llvm/include/llvm/Frontend/OpenMP/ClauseT.h (+11-3)
- (modified) llvm/include/llvm/Frontend/OpenMP/OMP.td (+15)
- (added) openmp/runtime/test/transform/interchange/foreach.cpp (+216)
- (added) openmp/runtime/test/transform/interchange/intfor.c (+38)
- (added) openmp/runtime/test/transform/interchange/iterfor.cpp (+222)
- (added) openmp/runtime/test/transform/interchange/parallel-wsloop-collapse-foreach.cpp (+340)
- (added) openmp/runtime/test/transform/interchange/parallel-wsloop-collapse-intfor.cpp (+106)
- (added) openmp/runtime/test/transform/reverse/foreach.cpp (+162)
- (added) openmp/runtime/test/transform/reverse/intfor.c (+25)
- (added) openmp/runtime/test/transform/reverse/iterfor.cpp (+164)
- (added) openmp/runtime/test/transform/reverse/parallel-wsloop-collapse-foreach.cpp (+285)
- (added) openmp/runtime/test/transform/reverse/parallel-wsloop-collapse-intfor.cpp (+51)
``````````diff
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 365b607c74117..a79aafbf20222 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2146,6 +2146,14 @@ enum CXCursorKind {
*/
CXCursor_OMPScopeDirective = 306,
+ /** OpenMP reverse directive.
+ */
+ CXCursor_OMPReverseDirective = 307,
+
+ /** OpenMP interchange directive.
+ */
+ CXCursor_OMPInterchangeDirective = 308,
+
/** OpenACC Compute Construct.
*/
CXCursor_OpenACCComputeConstruct = 320,
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 325a1baa44614..c381bbde9eb11 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -870,6 +870,106 @@ class OMPSizesClause final
}
};
+/// This class represents the 'permutation' clause in the
+/// '#pragma omp interchange' directive.
+///
+/// \code{c}
+/// #pragma omp interchange permutation(2,1)
+/// for (int i = 0; i < 64; ++i)
+/// for (int j = 0; j < 64; ++j)
+/// \endcode
+class OMPPermutationClause final
+ : public OMPClause,
+ private llvm::TrailingObjects<OMPSizesClause, Expr *> {
+ friend class OMPClauseReader;
+ friend class llvm::TrailingObjects<OMPSizesClause, Expr *>;
+
+ /// Location of '('.
+ SourceLocation LParenLoc;
+
+ /// Number of arguments in the clause, and hence also the number of loops to
+ /// be permuted.
+ unsigned NumLoops;
+
+ /// Build an empty clause.
+ explicit OMPPermutationClause(int NumLoops)
+ : OMPClause(llvm::omp::OMPC_permutation, SourceLocation(),
+ SourceLocation()),
+ NumLoops(NumLoops) {}
+
+public:
+ /// Build a 'permutation' clause AST node.
+ ///
+ /// \param C Context of the AST.
+ /// \param StartLoc Location of the 'permutation' identifier.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Location of ')'.
+ /// \param Args Content of the clause.
+ static OMPPermutationClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> Args);
+
+ /// Build an empty 'permutation' AST node for deserialization.
+ ///
+ /// \param C Context of the AST.
+ /// \param NumLoops Number of arguments in the clause.
+ static OMPPermutationClause *CreateEmpty(const ASTContext &C,
+ unsigned NumLoops);
+
+ /// Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
+ /// Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// Returns the number of list items.
+ unsigned getNumLoops() const { return NumLoops; }
+
+ /// Returns the permutation index expressions.
+ ///@{
+ MutableArrayRef<Expr *> getArgsRefs() {
+ return MutableArrayRef<Expr *>(static_cast<OMPPermutationClause *>(this)
+ ->template getTrailingObjects<Expr *>(),
+ NumLoops);
+ }
+ ArrayRef<Expr *> getArgsRefs() const {
+ return ArrayRef<Expr *>(static_cast<const OMPPermutationClause *>(this)
+ ->template getTrailingObjects<Expr *>(),
+ NumLoops);
+ }
+ ///@}
+
+ /// Sets the permutation index expressions.
+ void setArgRefs(ArrayRef<Expr *> VL) {
+ assert(VL.size() == NumLoops);
+ std::copy(VL.begin(), VL.end(),
+ static_cast<OMPPermutationClause *>(this)
+ ->template getTrailingObjects<Expr *>());
+ }
+
+ child_range children() {
+ MutableArrayRef<Expr *> Args = getArgsRefs();
+ return child_range(reinterpret_cast<Stmt **>(Args.begin()),
+ reinterpret_cast<Stmt **>(Args.end()));
+ }
+ const_child_range children() const {
+ ArrayRef<Expr *> Args = getArgsRefs();
+ return const_child_range(reinterpret_cast<Stmt *const *>(Args.begin()),
+ reinterpret_cast<Stmt *const *>(Args.end()));
+ }
+
+ child_range used_children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+ const_child_range used_children() const {
+ return const_child_range(const_child_iterator(), const_child_iterator());
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == llvm::omp::OMPC_permutation;
+ }
+};
+
/// Representation of the 'full' clause of the '#pragma omp unroll' directive.
///
/// \code
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index f9b145b4e86a5..7596b78c94f1c 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3004,6 +3004,12 @@ DEF_TRAVERSE_STMT(OMPTileDirective,
DEF_TRAVERSE_STMT(OMPUnrollDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPReverseDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPInterchangeDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
DEF_TRAVERSE_STMT(OMPForDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@@ -3302,6 +3308,14 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSizesClause(OMPSizesClause *C) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPPermutationClause(
+ OMPPermutationClause *C) {
+ for (Expr *E : C->getArgsRefs())
+ TRY_TO(TraverseStmt(E));
+ return true;
+}
+
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPFullClause(OMPFullClause *C) {
return true;
diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h
index f735fa5643aec..df6c485117c80 100644
--- a/clang/include/clang/AST/StmtOpenMP.h
+++ b/clang/include/clang/AST/StmtOpenMP.h
@@ -1007,8 +1007,9 @@ class OMPLoopTransformationDirective : public OMPLoopBasedDirective {
Stmt *getPreInits() const;
static bool classof(const Stmt *T) {
- return T->getStmtClass() == OMPTileDirectiveClass ||
- T->getStmtClass() == OMPUnrollDirectiveClass;
+ Stmt::StmtClass C = T->getStmtClass();
+ return C == OMPTileDirectiveClass || C == OMPUnrollDirectiveClass ||
+ C == OMPReverseDirectiveClass || C == OMPInterchangeDirectiveClass;
}
};
@@ -5638,6 +5639,147 @@ class OMPTileDirective final : public OMPLoopTransformationDirective {
}
};
+/// Represents the '#pragma omp reverse' loop transformation directive.
+///
+/// \code
+/// #pragma omp reverse
+/// for (int i = 0; i < n; ++i)
+/// ...
+/// \endcode
+class OMPReverseDirective final : public OMPLoopTransformationDirective {
+ friend class ASTStmtReader;
+ friend class OMPExecutableDirective;
+
+ /// Offsets of child members.
+ enum {
+ PreInitsOffset = 0,
+ TransformedStmtOffset,
+ };
+
+ explicit OMPReverseDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPLoopTransformationDirective(OMPReverseDirectiveClass,
+ llvm::omp::OMPD_reverse, StartLoc,
+ EndLoc, 1) {}
+
+ void setPreInits(Stmt *PreInits) {
+ Data->getChildren()[PreInitsOffset] = PreInits;
+ }
+
+ void setTransformedStmt(Stmt *S) {
+ Data->getChildren()[TransformedStmtOffset] = S;
+ }
+
+public:
+ /// Create a new AST node representation for '#pragma omp reverse'.
+ ///
+ /// \param C Context of the AST.
+ /// \param StartLoc Location of the introducer (e.g. the 'omp' token).
+ /// \param EndLoc Location of the directive's end (e.g. the tok::eod).
+ /// \param Clauses The directive's clauses.
+ /// \param AssociatedStmt The outermost associated loop.
+ /// \param TransformedStmt The loop nest after tiling, or nullptr in
+ /// dependent contexts.
+ /// \param PreInits Helper preinits statements for the loop nest.
+ static OMPReverseDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ Stmt *TransformedStmt, Stmt *PreInits);
+
+ /// Build an empty '#pragma omp reverse' AST node for deserialization.
+ ///
+ /// \param C Context of the AST.
+ /// \param NumClauses Number of clauses to allocate.
+ static OMPReverseDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses);
+
+ /// Gets/sets the associated loops after the transformation, i.e. after
+ /// de-sugaring.
+ Stmt *getTransformedStmt() const {
+ return Data->getChildren()[TransformedStmtOffset];
+ }
+
+ /// Return preinits statement.
+ Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPReverseDirectiveClass;
+ }
+};
+
+/// Represents the '#pragma omp interchange' loop transformation directive.
+///
+/// \code{c}
+/// #pragma omp interchange
+/// for (int i = 0; i < m; ++i)
+/// for (int j = 0; j < n; ++j)
+/// ..
+/// \endcode
+class OMPInterchangeDirective final : public OMPLoopTransformationDirective {
+ friend class ASTStmtReader;
+ friend class OMPExecutableDirective;
+
+ /// Offsets of child members.
+ enum {
+ PreInitsOffset = 0,
+ TransformedStmtOffset,
+ };
+
+ explicit OMPInterchangeDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned NumLoops)
+ : OMPLoopTransformationDirective(OMPInterchangeDirectiveClass,
+ llvm::omp::OMPD_interchange, StartLoc,
+ EndLoc, NumLoops) {
+ setNumGeneratedLoops(3 * NumLoops);
+ }
+
+ void setPreInits(Stmt *PreInits) {
+ Data->getChildren()[PreInitsOffset] = PreInits;
+ }
+
+ void setTransformedStmt(Stmt *S) {
+ Data->getChildren()[TransformedStmtOffset] = S;
+ }
+
+public:
+ /// Create a new AST node representation for '#pragma omp interchange'.
+ ///
+ /// \param C Context of the AST.
+ /// \param StartLoc Location of the introducer (e.g. the 'omp' token).
+ /// \param EndLoc Location of the directive's end (e.g. the tok::eod).
+ /// \param Clauses The directive's clauses.
+ /// \param NumLoops Number of affected loops
+ /// (number of items in the 'permutation' clause if present).
+ /// \param AssociatedStmt The outermost associated loop.
+ /// \param TransformedStmt The loop nest after tiling, or nullptr in
+ /// dependent contexts.
+ /// \param PreInits Helper preinits statements for the loop nest.
+ static OMPInterchangeDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, unsigned NumLoops, Stmt *AssociatedStmt,
+ Stmt *TransformedStmt, Stmt *PreInits);
+
+ /// Build an empty '#pragma omp interchange' AST node for deserialization.
+ ///
+ /// \param C Context of the AST.
+ /// \param NumClauses Number of clauses to allocate.
+ /// \param NumLoops Number of associated loops to allocate.
+ static OMPInterchangeDirective *
+ CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned NumLoops);
+
+ /// Gets the associated loops after the transformation. This is the de-sugared
+ /// replacement or nullptr in dependent contexts.
+ Stmt *getTransformedStmt() const {
+ return Data->getChildren()[TransformedStmtOffset];
+ }
+
+ /// Return preinits statement.
+ Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPInterchangeDirectiveClass;
+ }
+};
+
/// This represents the '#pragma omp unroll' loop transformation directive.
///
/// \code
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9e82130c93609..690912060f723 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11494,6 +11494,10 @@ def err_omp_dispatch_statement_call
" to a target function or an assignment to one">;
def err_omp_unroll_full_variable_trip_count : Error<
"loop to be fully unrolled must have a constant trip count">;
+def err_omp_interchange_permutation_value_range : Error<
+ "permutation index must be at least 1 and at most %0">;
+def err_omp_interchange_permutation_value_repeated : Error<
+ "index %0 must appear exactly once in the permutation clause">;
def note_omp_directive_here : Note<"'%0' directive found here">;
def err_omp_instantiation_not_supported
: Error<"instantiation of '%0' not supported yet">;
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 305f19daa4a92..b445ea225eac5 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -229,6 +229,8 @@ def OMPSimdDirective : StmtNode<OMPLoopDirective>;
def OMPLoopTransformationDirective : StmtNode<OMPLoopBasedDirective, 1>;
def OMPTileDirective : StmtNode<OMPLoopTransformationDirective>;
def OMPUnrollDirective : StmtNode<OMPLoopTransformationDirective>;
+def OMPReverseDirective : StmtNode<OMPLoopTransformationDirective>;
+def OMPInterchangeDirective : StmtNode<OMPLoopTransformationDirective>;
def OMPForDirective : StmtNode<OMPLoopDirective>;
def OMPForSimdDirective : StmtNode<OMPLoopDirective>;
def OMPSectionsDirective : StmtNode<OMPExecutableDirective>;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 61589fb7766f4..aea53673721bd 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3537,6 +3537,9 @@ class Parser : public CodeCompletionHandler {
/// Parses the 'sizes' clause of a '#pragma omp tile' directive.
OMPClause *ParseOpenMPSizesClause();
+ /// Parses the 'permutation' clause of a '#pragma omp interchange' directive.
+ OMPClause *ParseOpenMPPermutationClause();
+
/// Parses clause without any additional arguments.
///
/// \param Kind Kind of current clause.
diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h
index 51981e1c9a8b9..fe9d702b7af03 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -422,6 +422,17 @@ class SemaOpenMP : public SemaBase {
StmtResult ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
+ /// Called on well-formed '#pragma omp reverse' after parsing of its clauses
+ /// and the associated statement.
+ StmtResult ActOnOpenMPReverseDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '#pragma omp interchange' after parsing of its
+ /// clauses and the associated statement.
+ StmtResult ActOnOpenMPInterchangeDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
/// Called on well-formed '\#pragma omp for' after parsing
/// of the associated statement.
StmtResult
@@ -859,6 +870,11 @@ class SemaOpenMP : public SemaBase {
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// Called on well-form 'permutation' clause after parsing its arguments.
+ OMPClause *ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// Called on well-form 'full' clauses.
OMPClause *ActOnOpenMPFullClause(SourceLocation StartLoc,
SourceLocation EndLoc);
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index d3538e43d3d78..f488d1eca35c2 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1856,6 +1856,8 @@ enum StmtCode {
STMT_OMP_SIMD_DIRECTIVE,
STMT_OMP_TILE_DIRECTIVE,
STMT_OMP_UNROLL_DIRECTIVE,
+ STMT_OMP_REVERSE_DIRECTIVE,
+ STMT_OMP_INTERCHANGE_DIRECTIVE,
STMT_OMP_FOR_DIRECTIVE,
STMT_OMP_FOR_SIMD_DIRECTIVE,
STMT_OMP_SECTIONS_DIRECTIVE,
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 042a5df5906ca..c94310769ed9e 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -971,6 +971,25 @@ OMPSizesClause *OMPSizesClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPSizesClause(NumSizes);
}
+OMPPermutationClause *OMPPermutationClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> Args) {
+ OMPPermutationClause *Clause = CreateEmpty(C, Args.size());
+ Clause->setLocStart(StartLoc);
+ Clause->setLParenLoc(LParenLoc);
+ Clause->setLocEnd(EndLoc);
+ Clause->setArgRefs(Args);
+ return Clause;
+}
+
+OMPPermutationClause *OMPPermutationClause::CreateEmpty(const ASTContext &C,
+ unsigned NumLoops) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumLoops));
+ return new (Mem) OMPPermutationClause(NumLoops);
+}
+
OMPFullClause *OMPFullClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc) {
@@ -1774,6 +1793,18 @@ void OMPClausePrinter::VisitOMPSizesClause(OMPSizesClause *Node) {
OS << ")";
}
+void OMPClausePrinter::VisitOMPPermutationClause(OMPPermutationClause *Node) {
+ OS << "permutation(";
+ bool First = true;
+ for (Expr *Size : Node->getArgsRefs()) {
+ if (!First)
+ OS << ", ";
+ Size->printPretty(OS, nullptr, Policy, 0);
+ First = false;
+ }
+ OS << ")";
+}
+
void OMPClausePrinter::VisitOMPFullClause(OMPFullClause *Node) { OS << "full"; }
void OMPClausePrinter::VisitOMPPartialClause(OMPPartialClause *Node) {
diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp
index d8519b2071e6d..8a4a736263920 100644
--- a/clang/lib/AST/StmtOpenMP.cpp
+++ b/clang/lib/AST/StmtOpenMP.cpp
@@ -449,6 +449,45 @@ OMPUnrollDirective *OMPUnrollDirective::CreateEmpty(const ASTContext &C,
SourceLocation(), SourceLocation());
}
+OMPReverseDirective *
+OMPReverseDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ Stmt *TransformedStmt, Stmt *PreInits) {
+ OMPReverseDirective *Dir = createDirective<OMPReverseDirective>(
+ C, Clauses, AssociatedStmt, TransformedStmtOffset + 1, StartLoc, EndLoc);
+ Dir->setTransformedStmt(TransformedStmt);
+ Dir->setPreInits(PreInits);
+ return Dir;
+}
+
+OMPReverseDirective *OMPReverseDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses) {
+ return createEmptyDirective<OMPReverseDirective>(
+ C, NumClauses, /*HasAssociatedStmt=*/true, TransformedStmtOffset + 1,
+ SourceLocation(), SourceLocation());
+}
+
+OMPInterchangeDirective *OMPInterchangeDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, unsigned NumLoops, Stmt *AssociatedStmt,
+ Stmt *TransformedStmt, Stmt *PreInits) {
+ OMPInterchangeDirective *Dir = createDirective<OMPInterchangeDirective>(
+ C, Clauses, AssociatedStmt, TransformedStmtOffset + 1, StartLo...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/92030
More information about the llvm-branch-commits
mailing list