llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Michael Kruse (Meinersbur) <details> <summary>Changes</summary> Add the interchange directive 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). --- Patch is 185.81 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/93022.diff 30 Files Affected: - (modified) clang/include/clang-c/Index.h (+4) - (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+3) - (modified) clang/include/clang/AST/StmtOpenMP.h (+75-1) - (modified) clang/include/clang/Basic/StmtNodes.td (+1) - (modified) clang/include/clang/Sema/SemaOpenMP.h (+6) - (modified) clang/include/clang/Serialization/ASTBitCodes.h (+1) - (modified) clang/lib/AST/StmtOpenMP.cpp (+20) - (modified) clang/lib/AST/StmtPrinter.cpp (+5) - (modified) clang/lib/AST/StmtProfile.cpp (+5) - (modified) clang/lib/Basic/OpenMPKinds.cpp (+3-1) - (modified) clang/lib/CodeGen/CGStmt.cpp (+3) - (modified) clang/lib/CodeGen/CGStmtOpenMP.cpp (+10) - (modified) clang/lib/CodeGen/CodeGenFunction.h (+1) - (modified) clang/lib/Parse/ParseOpenMP.cpp (+2) - (modified) clang/lib/Sema/SemaExceptionSpec.cpp (+1) - (modified) clang/lib/Sema/SemaOpenMP.cpp (+162) - (modified) clang/lib/Sema/TreeTransform.h (+11) - (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+11) - (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+5) - (added) clang/test/OpenMP/interchange_ast_print.cpp (+135) - (added) clang/test/OpenMP/interchange_codegen.cpp (+1990) - (added) clang/test/OpenMP/interchange_messages.cpp (+77) - (modified) clang/tools/libclang/CIndex.cpp (+8) - (modified) clang/tools/libclang/CXCursor.cpp (+3) - (modified) llvm/include/llvm/Frontend/OpenMP/OMP.td (+3) - (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) ``````````diff diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index c7d63818ece23..a79aafbf20222 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2150,6 +2150,10 @@ enum CXCursorKind { */ CXCursor_OMPReverseDirective = 307, + /** OpenMP interchange directive. + */ + CXCursor_OMPInterchangeDirective = 308, + /** OpenACC Compute Construct. */ CXCursor_OpenACCComputeConstruct = 320, diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 06b29d59785f6..1bb167d7ddc3c 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -3024,6 +3024,9 @@ DEF_TRAVERSE_STMT(OMPUnrollDirective, DEF_TRAVERSE_STMT(OMPReverseDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPInterchangeDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index fb7f413162fad..01c8b8e1a9f5e 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -1009,7 +1009,7 @@ class OMPLoopTransformationDirective : public OMPLoopBasedDirective { static bool classof(const Stmt *T) { Stmt::StmtClass C = T->getStmtClass(); return C == OMPTileDirectiveClass || C == OMPUnrollDirectiveClass || - C == OMPReverseDirectiveClass; + C == OMPReverseDirectiveClass || C == OMPInterchangeDirectiveClass; } }; @@ -5777,6 +5777,80 @@ class OMPReverseDirective final : public OMPLoopTransformationDirective { } }; +/// 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 '#pragma omp scan' directive. /// /// \code diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index b2e2be5c998bb..b445ea225eac5 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -230,6 +230,7 @@ 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/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h index ca91bffe24f6f..06376f173e8df 100644 --- a/clang/include/clang/Sema/SemaOpenMP.h +++ b/clang/include/clang/Sema/SemaOpenMP.h @@ -425,6 +425,12 @@ class SemaOpenMP : public SemaBase { /// Called on well-formed '#pragma omp reverse'. StmtResult ActOnOpenMPReverseDirective(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 diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index dee0d073557cc..5fbdfd7a496fe 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1857,6 +1857,7 @@ enum StmtCode { 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/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp index 83b8a08e9af73..24d8eb25c59ba 100644 --- a/clang/lib/AST/StmtOpenMP.cpp +++ b/clang/lib/AST/StmtOpenMP.cpp @@ -467,6 +467,26 @@ OMPReverseDirective *OMPReverseDirective::CreateEmpty(const ASTContext &C, 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, StartLoc, EndLoc, + NumLoops); + Dir->setTransformedStmt(TransformedStmt); + Dir->setPreInits(PreInits); + return Dir; +} + +OMPInterchangeDirective * +OMPInterchangeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, + unsigned NumLoops) { + return createEmptyDirective<OMPInterchangeDirective>( + C, NumClauses, /*HasAssociatedStmt=*/true, TransformedStmtOffset + 1, + SourceLocation(), SourceLocation(), NumLoops); +} + OMPForSimdDirective * OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 64b481f680311..64bee75b205ae 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -768,6 +768,11 @@ void StmtPrinter::VisitOMPReverseDirective(OMPReverseDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPInterchangeDirective(OMPInterchangeDirective *Node) { + Indent() << "#pragma omp interchange"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPForDirective(OMPForDirective *Node) { Indent() << "#pragma omp for"; PrintOMPExecutableDirective(Node); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 7445e5519b972..1ae99d43575a7 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -989,6 +989,11 @@ void StmtProfiler::VisitOMPReverseDirective(const OMPReverseDirective *S) { VisitOMPLoopTransformationDirective(S); } +void StmtProfiler::VisitOMPInterchangeDirective( + const OMPInterchangeDirective *S) { + VisitOMPLoopTransformationDirective(S); +} + void StmtProfiler::VisitOMPForDirective(const OMPForDirective *S) { VisitOMPLoopDirective(S); } diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 803808c38e2fe..ff5d5c8bdc981 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -684,7 +684,8 @@ bool clang::isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind) { } bool clang::isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind) { - return DKind == OMPD_tile || DKind == OMPD_unroll || DKind == OMPD_reverse; + return DKind == OMPD_tile || DKind == OMPD_unroll || DKind == OMPD_reverse || + DKind == OMPD_interchange; } bool clang::isOpenMPCombinedParallelADirective(OpenMPDirectiveKind DKind) { @@ -809,6 +810,7 @@ void clang::getOpenMPCaptureRegions( case OMPD_tile: case OMPD_unroll: case OMPD_reverse: + case OMPD_interchange: // loop transformations do not introduce captures. break; case OMPD_threadprivate: diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 93c2f8900dd12..ba7c52cc6ab7b 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -225,6 +225,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) { case Stmt::OMPReverseDirectiveClass: EmitOMPReverseDirective(cast<OMPReverseDirective>(*S)); break; + case Stmt::OMPInterchangeDirectiveClass: + EmitOMPInterchangeDirective(cast<OMPInterchangeDirective>(*S)); + break; case Stmt::OMPForDirectiveClass: EmitOMPForDirective(cast<OMPForDirective>(*S)); break; diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index ad6c044aa483b..7a37e452fb559 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -189,6 +189,9 @@ class OMPLoopScope : public CodeGenFunction::RunCleanupsScope { PreInits = Unroll->getPreInits(); } else if (const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) { PreInits = Reverse->getPreInits(); + } else if (const auto *Interchange = + dyn_cast<OMPInterchangeDirective>(&S)) { + PreInits = Interchange->getPreInits(); } else { llvm_unreachable("Unknown loop-based directive kind."); } @@ -2770,6 +2773,13 @@ void CodeGenFunction::EmitOMPReverseDirective(const OMPReverseDirective &S) { EmitStmt(S.getTransformedStmt()); } +void CodeGenFunction::EmitOMPInterchangeDirective( + const OMPInterchangeDirective &S) { + // Emit the de-sugared statement. + OMPTransformDirectiveScopeRAII InterchangeScope(*this, &S); + EmitStmt(S.getTransformedStmt()); +} + void CodeGenFunction::EmitOMPUnrollDirective(const OMPUnrollDirective &S) { bool UseOMPIRBuilder = CGM.getLangOpts().OpenMPIRBuilder; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index ac738e1e82886..c2a8e65ca2d0a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3808,6 +3808,7 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitOMPTileDirective(const OMPTileDirective &S); void EmitOMPUnrollDirective(const OMPUnrollDirective &S); void EmitOMPReverseDirective(const OMPReverseDirective &S); + void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S); void EmitOMPForDirective(const OMPForDirective &S); void EmitOMPForSimdDirective(const OMPForSimdDirective &S); void EmitOMPSectionsDirective(const OMPSectionsDirective &S); diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 57fcf6ce520ac..0e3e604203c86 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -2385,6 +2385,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_tile: case OMPD_unroll: case OMPD_reverse: + case OMPD_interchange: case OMPD_task: case OMPD_taskyield: case OMPD_barrier: @@ -2804,6 +2805,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( case OMPD_tile: case OMPD_unroll: case OMPD_reverse: + case OMPD_interchange: case OMPD_for: case OMPD_for_simd: case OMPD_sections: diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 4de7183cde281..5991f496d3a0f 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1487,6 +1487,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) { case Stmt::OMPTileDirectiveClass: case Stmt::OMPUnrollDirectiveClass: case Stmt::OMPReverseDirectiveClass: + case Stmt::OMPInterchangeDirectiveClass: case Stmt::OMPSingleDirectiveClass: case Stmt::OMPTargetDataDirectiveClass: case Stmt::OMPTargetDirectiveClass: diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index c2fd4de933ae4..ef141003b7d61 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -39,6 +39,7 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/PointerEmbeddedInt.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Sequence.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Frontend/OpenMP/OMPAssume.h" @@ -4335,6 +4336,7 @@ void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, case OMPD_tile: case OMPD_unroll: case OMPD_reverse: + case OMPD_interchange: break; case OMPD_loop: // TODO: 'loop' may require additional parameters depending on the binding. @@ -6552,6 +6554,10 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( "reverse directive does not support any clauses"); Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc); break; + case OMPD_interchange: + Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc, + EndLoc); + break; case OMPD_for: Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); @@ -15139,6 +15145,8 @@ bool SemaOpenMP::checkTransformableLoopNest( DependentPreInits = Dir->getPreInits(); else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform)) DependentPreInits = Dir->getPreInits(); + else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform)) + DependentPreInits = Dir->getPreInits(); else llvm_unreachable("Unhandled loop transformation"); @@ -15937,6 +15945,160 @@ StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt, buildPreInits(Context, PreInits)); } +StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc) { + ASTContext &Context = getASTContext(); + DeclContext *CurContext = SemaRef.CurContext; + Scope *CurScope = SemaRef.getCurScope(); + + // Empty statement should only be possible if there already was an error. + if (!AStmt) + return StmtError(); + + // interchange without permutation clause swaps two loops. + constexpr size_t NumLoops = 2; + + // Verify and diagnose loop nest. + SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops); + Stmt *Body = nullptr; + SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits; + if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops, + LoopHelpers, Body, OriginalInits)) + return StmtError(); + + // Delay interchange to when template is completely instantiated. + if (CurContext->isDependentContext()) + return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses, + NumLoops, AStmt, nullptr, nullptr); + + assert(LoopHelpers.size() == NumLoops && + "Expecting loop iteration space dimensionaly to match number of " + "affected loops"); + assert(OriginalInits.size() == NumLoops && + "Expecting loop iteration space dimensionaly to match number of " + "affected loops"); + + // Decode the permutation clause. + constexpr uint64_t Permutation[] = {1, 0}; + + // Find the affected loops. + SmallVector<Stmt *> LoopStmts(NumLoops, nullptr); + collectLoopStmts(AStmt, LoopStmts); + + // Collect pre-init statements on the order before the permuation. + SmallVector<Stmt *> PreInits; + for (auto I : llvm::seq<int>(NumLoops)) { + OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I]; + + assert(LoopHelper.Counters.size() == 1 && + "Single-dimensional loop iteration space expected"); + auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front()); + + std::string OrigVarName = OrigCntVar->getNameInfo().getAsString(); + addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I], + PreInits); + } + + SmallVector<VarDecl *> PermutedIndVars; + PermutedIndVars.resize(NumLoops); + CaptureVars CopyTransformer(SemaRef); + + // Create the permuted loops from the inside to the outside of the + // interchanged loop nest. Body of the innermost new loop is the original + // innermost body. + Stmt *Inner = Body; + for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) { + // Get the original loop that belongs to this new position. + uint64_t SourceIdx = Permutation[TargetIdx]; + OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx]; + Stmt *SourceLoopStmt = LoopStmts[SourceIdx]; + assert(SourceHelper.Counters.size() == 1 && + "Single-dimensional loop iteration space expected"); + auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front()); + + // Normalized loop counter variable: From 0 to n-1, always an integer type. + DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef); + QualType IVTy = IterVarRef->getType(); + assert(IVTy->isIntegerType() && + "Expected the logical iteration counter to be an integer"); + + std::string OrigVarName = OrigCntVar->getNameInfo().getAsString(); + SourceLocation OrigVarLoc = IterVarRef->getExprLoc(); + + // Make a copy of the NumIterations expression for each use: By the AST + // constraints, every expression object in a DeclContext must be unique. + auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * { + return AssertSuccess( + CopyTransformer.TransformExpr(SourceHelper.NumIterations)); + }; + + // Iteration variable for the permuted loop. Reuse the one from + // checkOpenMPLoop which will also be used to update the original loop + // variable. + std::string PermutedCntName = + (Twine(".permuted_") + llvm::utostr(TargetIdx) + ".iv." + OrigVarName) + .str(); + auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl()); + PermutedCntDecl->setDeclName( + &SemaRef.P... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/93022 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits