[llvm-branch-commits] [clang] [flang] [llvm] [openmp] [Clang][OpenMP] Add reverse and interchange directives (PR #92030)
https://github.com/Meinersbur edited https://github.com/llvm/llvm-project/pull/92030 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [flang] [llvm] [openmp] [Clang][OpenMP] Add reverse and interchange directives (PR #92030)
https://github.com/Meinersbur edited https://github.com/llvm/llvm-project/pull/92030 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [flang] [llvm] [openmp] [Clang][OpenMP] Add reverse and interchange directives (PR #92030)
@@ -15745,6 +15760,388 @@ StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef Clauses, buildPreInits(Context, PreInits)); } +StmtResult +SemaOpenMP::ActOnOpenMPReverseDirective(ArrayRef Clauses, +Stmt *AStmt, SourceLocation StartLoc, +SourceLocation EndLoc) { + ASTContext = getASTContext(); + Scope *CurScope = SemaRef.getCurScope(); + assert(Clauses.empty() && "reverse directive does not accept any clauses; " +"must have beed checked before"); + + // Empty statement should only be possible if there already was an error. + if (!AStmt) +return StmtError(); + + constexpr unsigned NumLoops = 1; + Stmt *Body = nullptr; + SmallVector LoopHelpers( + NumLoops); + SmallVector, NumLoops + 1> OriginalInits; + if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers, + Body, OriginalInits)) +return StmtError(); + + // Delay applying the transformation to when template is completely + // instantiated. + if (SemaRef.CurContext->isDependentContext()) +return OMPReverseDirective::Create(Context, StartLoc, EndLoc, Clauses, + AStmt, nullptr, nullptr); + + assert(LoopHelpers.size() == NumLoops && + "Expecting a single-dimensional loop iteration space"); + assert(OriginalInits.size() == NumLoops && + "Expecting a single-dimensional loop iteration space"); + OMPLoopBasedDirective::HelperExprs = LoopHelpers.front(); + + // Find the loop statement. + Stmt *LoopStmt = nullptr; + collectLoopStmts(AStmt, {LoopStmt}); + + // Determine the PreInit declarations. + SmallVector PreInits; + addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits); + + auto *IterationVarRef = cast(LoopHelper.IterationVarRef); + QualType IVTy = IterationVarRef->getType(); + uint64_t IVWidth = Context.getTypeSize(IVTy); + auto *OrigVar = cast(LoopHelper.Counters.front()); + + // Iteration variable SourceLocations. + SourceLocation OrigVarLoc = OrigVar->getExprLoc(); + SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc(); + SourceLocation OrigVarLocEnd = OrigVar->getEndLoc(); + + // Locations pointing to the transformation. + SourceLocation TransformLoc = StartLoc; + SourceLocation TransformLocBegin = StartLoc; + SourceLocation TransformLocEnd = EndLoc; + + // Internal variable names. + std::string OrigVarName = OrigVar->getNameInfo().getAsString(); + std::string TripCountName = (Twine(".tripcount.") + OrigVarName).str(); + std::string ForwardIVName = (Twine(".forward.iv.") + OrigVarName).str(); + std::string ReversedIVName = (Twine(".reversed.iv.") + OrigVarName).str(); + + // LoopHelper.Updates will read the logical iteration number from + // LoopHelper.IterationVarRef, compute the value of the user loop counter of + // that logical iteration from it, then assign it to the user loop counter + // variable. We cannot directly use LoopHelper.IterationVarRef as the + // induction variable of the generated loop because it may cause an underflow: + // \code + // for (unsigned i = 0; i < n; ++i) + // body(i); + // \endcode + // + // Naive reversal: + // \code + // for (unsigned i = n-1; i >= 0; ++i) alexey-bataev wrote: ```suggestion // for (unsigned i = n-1; i >= 0; --i) ``` https://github.com/llvm/llvm-project/pull/92030 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [flang] [llvm] [openmp] [Clang][OpenMP] Add reverse and interchange directives (PR #92030)
@@ -15745,6 +15760,388 @@ StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef Clauses, buildPreInits(Context, PreInits)); } +StmtResult +SemaOpenMP::ActOnOpenMPReverseDirective(ArrayRef Clauses, +Stmt *AStmt, SourceLocation StartLoc, +SourceLocation EndLoc) { + ASTContext = getASTContext(); + Scope *CurScope = SemaRef.getCurScope(); + assert(Clauses.empty() && "reverse directive does not accept any clauses; " +"must have beed checked before"); + + // Empty statement should only be possible if there already was an error. + if (!AStmt) +return StmtError(); + + constexpr unsigned NumLoops = 1; + Stmt *Body = nullptr; + SmallVector LoopHelpers( + NumLoops); + SmallVector, NumLoops + 1> OriginalInits; + if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers, + Body, OriginalInits)) +return StmtError(); + + // Delay applying the transformation to when template is completely + // instantiated. + if (SemaRef.CurContext->isDependentContext()) +return OMPReverseDirective::Create(Context, StartLoc, EndLoc, Clauses, + AStmt, nullptr, nullptr); + + assert(LoopHelpers.size() == NumLoops && + "Expecting a single-dimensional loop iteration space"); + assert(OriginalInits.size() == NumLoops && + "Expecting a single-dimensional loop iteration space"); + OMPLoopBasedDirective::HelperExprs = LoopHelpers.front(); + + // Find the loop statement. + Stmt *LoopStmt = nullptr; + collectLoopStmts(AStmt, {LoopStmt}); + + // Determine the PreInit declarations. + SmallVector PreInits; + addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits); + + auto *IterationVarRef = cast(LoopHelper.IterationVarRef); + QualType IVTy = IterationVarRef->getType(); + uint64_t IVWidth = Context.getTypeSize(IVTy); + auto *OrigVar = cast(LoopHelper.Counters.front()); + + // Iteration variable SourceLocations. + SourceLocation OrigVarLoc = OrigVar->getExprLoc(); + SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc(); + SourceLocation OrigVarLocEnd = OrigVar->getEndLoc(); + + // Locations pointing to the transformation. + SourceLocation TransformLoc = StartLoc; + SourceLocation TransformLocBegin = StartLoc; + SourceLocation TransformLocEnd = EndLoc; + + // Internal variable names. + std::string OrigVarName = OrigVar->getNameInfo().getAsString(); + std::string TripCountName = (Twine(".tripcount.") + OrigVarName).str(); + std::string ForwardIVName = (Twine(".forward.iv.") + OrigVarName).str(); + std::string ReversedIVName = (Twine(".reversed.iv.") + OrigVarName).str(); + + // LoopHelper.Updates will read the logical iteration number from + // LoopHelper.IterationVarRef, compute the value of the user loop counter of + // that logical iteration from it, then assign it to the user loop counter + // variable. We cannot directly use LoopHelper.IterationVarRef as the + // induction variable of the generated loop because it may cause an underflow: + // \code + // for (unsigned i = 0; i < n; ++i) + // body(i); + // \endcode + // + // Naive reversal: + // \code + // for (unsigned i = n-1; i >= 0; ++i) + // body(i); + // \endcode + // + // Instead, we introduce a new iteration variable representing the logical + // iteration counter of the original loop, convert it to the logical iteration + // number of the reversed loop, then let LoopHelper.Updates compute the user's + // loop iteration variable from it. + // \code + // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) { + // auto .reversed.iv = n - .forward.iv - 1; + // i = (.reversed.iv + 0) * 1 // LoopHelper.Updates + // body(i); // Body + // } + // \endcode + + // Subexpressions with more than one use. One of the constraints of an AST is + // that every node object must appear at most once, hence we define a lambda + // that creates a new AST node at every use. + CaptureVars CopyTransformer(SemaRef); + auto MakeNumIterations = [, ]() -> Expr * { +return AssertSuccess( +CopyTransformer.TransformExpr(LoopHelper.NumIterations)); + }; + + // Create the iteration variable for the forward loop (from 0 to n-1). + VarDecl *ForwardIVDecl = + buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar); + auto MakeForwardRef = [ = this->SemaRef, ForwardIVDecl, IVTy, + OrigVarLoc]() { +return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc); + }; + + // Iteration variable for the reversed induction variable (from n-1 downto 0): + // Reuse the iteration variable created by checkOpenMPLoop. + auto *ReversedIVDecl = cast(IterationVarRef->getDecl()); + ReversedIVDecl->setDeclName( +
[llvm-branch-commits] [clang] [flang] [llvm] [openmp] [Clang][OpenMP] Add reverse and interchange directives (PR #92030)
@@ -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 { + friend class OMPClauseReader; + friend class llvm::TrailingObjects; + + /// 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 EndLocLocation of ')'. + /// \param Args Content of the clause. + static OMPPermutationClause * + Create(const ASTContext , SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef Args); + + /// Build an empty 'permutation' AST node for deserialization. + /// + /// \param CContext of the AST. + /// \param NumLoops Number of arguments in the clause. + static OMPPermutationClause *CreateEmpty(const ASTContext , + 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 getArgsRefs() { +return MutableArrayRef(static_cast(this) + ->template getTrailingObjects(), + NumLoops); + } + ArrayRef getArgsRefs() const { +return ArrayRef(static_cast(this) +->template getTrailingObjects(), +NumLoops); + } + ///@} + + /// Sets the permutation index expressions. + void setArgRefs(ArrayRef VL) { +assert(VL.size() == NumLoops); +std::copy(VL.begin(), VL.end(), + static_cast(this) + ->template getTrailingObjects()); + } + alexey-bataev wrote: This should be private https://github.com/llvm/llvm-project/pull/92030 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [flang] [llvm] [openmp] [Clang][OpenMP] Add reverse and interchange directives (PR #92030)
@@ -2146,6 +2146,14 @@ enum CXCursorKind { */ CXCursor_OMPScopeDirective = 306, + /** OpenMP reverse directive. + */ + CXCursor_OMPReverseDirective = 307, + alexey-bataev wrote: Split this into 2 patches, one for reverse, one for interchange https://github.com/llvm/llvm-project/pull/92030 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [flang] [llvm] [openmp] [Clang][OpenMP] Add reverse and interchange directives (PR #92030)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Michael Kruse (Meinersbur) Changes 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 { + friend class OMPClauseReader; + friend class llvm::TrailingObjects; + + /// Location of '('. + SourceLocation LParenLoc; + + /// Number of arguments in the clause, and hence also the number of loops to + /// be permuted. + unsigned NumLoops; +
[llvm-branch-commits] [clang] [flang] [llvm] [openmp] [Clang][OpenMP] Add reverse and interchange directives (PR #92030)
https://github.com/Meinersbur ready_for_review https://github.com/llvm/llvm-project/pull/92030 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [flang] [llvm] [openmp] [Clang][OpenMP] Add reverse and interchange directives (PR #92030)
Meinersbur wrote: Buildkite failure is unrelated: `fatal error C1060: compiler is out of heap space` https://github.com/llvm/llvm-project/pull/92030 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits