[llvm-branch-commits] [clang] [flang] [llvm] [openmp] [Clang][OpenMP] Add reverse and interchange directives (PR #92030)

2024-05-21 Thread Michael Kruse via llvm-branch-commits

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)

2024-05-21 Thread Michael Kruse via llvm-branch-commits

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)

2024-05-14 Thread Alexey Bataev via llvm-branch-commits


@@ -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)

2024-05-14 Thread Alexey Bataev via llvm-branch-commits


@@ -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)

2024-05-14 Thread Alexey Bataev via llvm-branch-commits


@@ -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)

2024-05-14 Thread Alexey Bataev via llvm-branch-commits


@@ -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)

2024-05-14 Thread via llvm-branch-commits

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)

2024-05-14 Thread Michael Kruse via llvm-branch-commits

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)

2024-05-14 Thread Michael Kruse via llvm-branch-commits

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