[clang] [flang] [llvm] [OpenMP] Introduce "loop sequence" as directive association (PR #168934)
Krzysztof Parzyszek via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 20 11:21:06 PST 2025
https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/168934
OpenMP 6.0 introduced a `fuse` directive, and with it a "loop sequence" as the associated code. What used to be "loop association" has become "loop-nest association".
Rename Association::Loop to LoopNest, add Association::LoopSeq to represent the "loop sequence" association.
Change the association of fuse from "block" to "loop sequence".
>From 01a417701b5a758910d17ecfb1f4e99fca0f5e9d Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 20 Nov 2025 13:14:16 -0600
Subject: [PATCH] [OpenMP] Introduce "loop sequence" as directive association
OpenMP 6.0 introduced a `fuse` directive, and with it a "loop sequence"
as the associated code. What used to be "loop association" has become
"loop-nest association".
Rename Association::Loop to LoopNest, add Association::LoopSeq to
represent the "loop sequence" association.
Change the association of fuse from "block" to "loop sequence".
---
clang/lib/Basic/OpenMPKinds.cpp | 4 ++--
flang/lib/Lower/OpenMP/OpenMP.cpp | 4 ++--
.../llvm/Frontend/Directive/DirectiveBase.td | 5 ++--
llvm/include/llvm/Frontend/OpenACC/ACC.td | 2 +-
llvm/include/llvm/Frontend/OpenMP/OMP.td | 24 +++++++++----------
llvm/lib/Frontend/OpenMP/OMP.cpp | 4 ++--
llvm/test/TableGen/directive1.td | 5 ++--
llvm/test/TableGen/directive2.td | 5 ++--
.../utils/TableGen/Basic/DirectiveEmitter.cpp | 19 ++++++++-------
9 files changed, 38 insertions(+), 34 deletions(-)
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 8e60fc26a7947..03485b7e81abc 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -680,7 +680,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
}
bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) {
- return getDirectiveAssociation(DKind) == Association::Loop;
+ return getDirectiveAssociation(DKind) == Association::LoopNest;
}
bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
@@ -741,7 +741,7 @@ bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) {
bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) {
// Avoid OMPD_declare_simd
- if (getDirectiveAssociation(DKind) != Association::Loop)
+ if (getDirectiveAssociation(DKind) != Association::LoopNest)
return false;
// Formally, OMPD_end_do_simd also has a loop association, but
// it's a Fortran-specific directive.
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index c6487349c4056..2e43e3d94cb8c 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -1202,7 +1202,7 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info,
// Start with privatization, so that the lowering of the nested
// code will use the right symbols.
bool isLoop = llvm::omp::getDirectiveAssociation(info.dir) ==
- llvm::omp::Association::Loop;
+ llvm::omp::Association::LoopNest;
bool privatize = info.clauses && info.privatize;
firOpBuilder.setInsertionPoint(marker);
@@ -3398,7 +3398,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
};
bool loopLeaf = llvm::omp::getDirectiveAssociation(item->id) ==
- llvm::omp::Association::Loop;
+ llvm::omp::Association::LoopNest;
if (loopLeaf) {
symTable.pushScope();
if (genOMPCompositeDispatch(converter, symTable, stmtCtx, semaCtx, eval,
diff --git a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
index 301a7cce59627..2aa0649479023 100644
--- a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
+++ b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
@@ -162,7 +162,8 @@ def AS_Block : Association<"Block"> {} // Block (incl. single
def AS_Declaration : Association<"Declaration"> {} // Declaration
def AS_Delimited : Association<"Delimited"> {} // Region delimited with
// begin/end
-def AS_Loop : Association<"Loop"> {} // Loop
+def AS_LoopNest : Association<"LoopNest"> {} // Loop nest
+def AS_LoopSeq : Association<"LoopSeq"> {} // Loop sequence
def AS_Separating : Association<"Separating"> {} // Separates parts of a
// construct
@@ -173,7 +174,7 @@ def AS_FromLeaves : Association<"FromLeaves"> {} // See below
// x + y = y + x
// x + x = x
// AS_None + x = x
-// AS_Block + AS_Loop = AS_Loop
+// AS_Block + AS_Loop{Nest|Seq} = AS_Loop{Nest|Seq}
// Other combinations are not allowed.
// This association is not valid for leaf constructs.
// The name "AS_FromLeaves" is recognized by TableGen, and there is no enum
diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td
index 65751839ceb09..7381ec7bff0c4 100644
--- a/llvm/include/llvm/Frontend/OpenACC/ACC.td
+++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td
@@ -419,7 +419,7 @@ def ACC_Loop : Directive<[Spelling<"loop">]> {
VersionedClause<ACCC_Independent>,
VersionedClause<ACCC_Seq>
];
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
}
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index a01858fb220f1..ade00e7ca27d5 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -859,7 +859,7 @@ def OMP_Distribute : Directive<[Spelling<"distribute">]> {
VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_Order, 50>,
];
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
}
def OMP_Do : Directive<[Spelling<"do">]> {
@@ -877,7 +877,7 @@ def OMP_Do : Directive<[Spelling<"do">]> {
VersionedClause<OMPC_Ordered>,
VersionedClause<OMPC_Schedule>,
];
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
let languages = [L_Fortran];
}
@@ -926,7 +926,7 @@ def OMP_For : Directive<[Spelling<"for">]> {
VersionedClause<OMPC_Reduction>,
VersionedClause<OMPC_Schedule>,
];
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
let languages = [L_C];
}
@@ -940,14 +940,14 @@ def OMP_Groupprivate : Directive<[Spelling<"groupprivate">]> {
}
def OMP_Fuse : Directive<[Spelling<"fuse">]> {
let allowedOnceClauses = [VersionedClause<OMPC_LoopRange, 60>];
- let association = AS_Block;
+ let association = AS_LoopSeq;
let category = CA_Executable;
}
def OMP_Interchange : Directive<[Spelling<"interchange">]> {
let allowedOnceClauses = [
VersionedClause<OMPC_Permutation>,
];
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
}
def OMP_interop : Directive<[Spelling<"interop">]> {
@@ -973,7 +973,7 @@ def OMP_loop : Directive<[Spelling<"loop">]> {
VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_Order, 50>,
];
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
}
def OMP_masked : Directive<[Spelling<"masked">]> {
@@ -1056,7 +1056,7 @@ def OMP_Requires : Directive<[Spelling<"requires">]> {
let category = CA_Informational;
}
def OMP_Reverse : Directive<[Spelling<"reverse">]> {
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
}
def OMP_Scan : Directive<[Spelling<"scan">]> {
@@ -1131,7 +1131,7 @@ def OMP_Simd : Directive<[Spelling<"simd">]> {
VersionedClause<OMPC_SafeLen>,
VersionedClause<OMPC_SimdLen>,
];
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
}
def OMP_Single : Directive<[Spelling<"single">]> {
@@ -1323,7 +1323,7 @@ def OMP_TaskLoop : Directive<[Spelling<"taskloop">]> {
VersionedClause<OMPC_GrainSize>,
VersionedClause<OMPC_NumTasks>,
];
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
}
def OMP_TaskWait : Directive<[Spelling<"taskwait">]> {
@@ -1371,14 +1371,14 @@ def OMP_Tile : Directive<[Spelling<"tile">]> {
let requiredClauses = [
VersionedClause<OMPC_Sizes, 51>,
];
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
}
def OMP_Stripe : Directive<[Spelling<"stripe">]> {
let allowedOnceClauses = [
VersionedClause<OMPC_Sizes, 60>,
];
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
}
def OMP_Unknown : Directive<[Spelling<"unknown">]> {
@@ -1391,7 +1391,7 @@ def OMP_Unroll : Directive<[Spelling<"unroll">]> {
VersionedClause<OMPC_Full, 51>,
VersionedClause<OMPC_Partial, 51>,
];
- let association = AS_Loop;
+ let association = AS_LoopNest;
let category = CA_Executable;
}
def OMP_Workshare : Directive<[Spelling<"workshare">]> {
diff --git a/llvm/lib/Frontend/OpenMP/OMP.cpp b/llvm/lib/Frontend/OpenMP/OMP.cpp
index f12941492547e..97aecf92ca5f3 100644
--- a/llvm/lib/Frontend/OpenMP/OMP.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMP.cpp
@@ -53,7 +53,7 @@ getFirstCompositeRange(iterator_range<ArrayRef<Directive>::iterator> Leafs) {
auto firstLoopAssociated =
[](iterator_range<ArrayRef<Directive>::iterator> List) {
for (auto It = List.begin(), End = List.end(); It != End; ++It) {
- if (getDirectiveAssociation(*It) == Association::Loop)
+ if (getDirectiveAssociation(*It) == Association::LoopNest)
return It;
}
return List.end();
@@ -71,7 +71,7 @@ getFirstCompositeRange(iterator_range<ArrayRef<Directive>::iterator> Leafs) {
return Empty;
for (; End != Leafs.end(); ++End) {
- if (getDirectiveAssociation(*End) != Association::Loop)
+ if (getDirectiveAssociation(*End) != Association::LoopNest)
break;
}
return llvm::make_range(Begin, End);
diff --git a/llvm/test/TableGen/directive1.td b/llvm/test/TableGen/directive1.td
index 5bd7890e0ddd1..3a9e8701c06eb 100644
--- a/llvm/test/TableGen/directive1.td
+++ b/llvm/test/TableGen/directive1.td
@@ -71,13 +71,14 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-NEXT: First_ = Block,
// CHECK-NEXT: Declaration,
// CHECK-NEXT: Delimited,
-// CHECK-NEXT: Loop,
+// CHECK-NEXT: LoopNest,
+// CHECK-NEXT: LoopSeq,
// CHECK-NEXT: None,
// CHECK-NEXT: Separating,
// CHECK-NEXT: Last_ = Separating,
// CHECK-NEXT: };
// CHECK-EMPTY:
-// CHECK-NEXT: static constexpr std::size_t Association_enumSize = 6;
+// CHECK-NEXT: static constexpr std::size_t Association_enumSize = 7;
// CHECK-EMPTY:
// CHECK-NEXT: enum class Category {
// CHECK-NEXT: Declarative,
diff --git a/llvm/test/TableGen/directive2.td b/llvm/test/TableGen/directive2.td
index eaaf82ddaaf41..392423faed36f 100644
--- a/llvm/test/TableGen/directive2.td
+++ b/llvm/test/TableGen/directive2.td
@@ -62,13 +62,14 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-NEXT: First_ = Block,
// CHECK-NEXT: Declaration,
// CHECK-NEXT: Delimited,
-// CHECK-NEXT: Loop,
+// CHECK-NEXT: LoopNest,
+// CHECK-NEXT: LoopSeq,
// CHECK-NEXT: None,
// CHECK-NEXT: Separating,
// CHECK-NEXT: Last_ = Separating,
// CHECK-NEXT: };
// CHECK-EMPTY:
-// CHECK-NEXT: static constexpr std::size_t Association_enumSize = 6;
+// CHECK-NEXT: static constexpr std::size_t Association_enumSize = 7;
// CHECK-EMPTY:
// CHECK-NEXT: enum class Category {
// CHECK-NEXT: Declarative,
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
index 3a488ed952210..1126c83034b54 100644
--- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
@@ -729,11 +729,12 @@ static void emitLeafTable(const DirectiveLanguage &DirLang, raw_ostream &OS,
static void generateGetDirectiveAssociation(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
enum struct Association {
- None = 0, // None should be the smallest value.
- Block, // The values of the rest don't matter.
- Declaration,
+ None = 0, // None should be the smallest value.
+ Block, // If the order of the rest of these changes, update the
+ Declaration, // 'Reduce' function below.
Delimited,
- Loop,
+ LoopNest,
+ LoopSeq,
Separating,
FromLeaves,
Invalid,
@@ -746,7 +747,8 @@ static void generateGetDirectiveAssociation(const DirectiveLanguage &DirLang,
.Case("AS_Block", Association::Block)
.Case("AS_Declaration", Association::Declaration)
.Case("AS_Delimited", Association::Delimited)
- .Case("AS_Loop", Association::Loop)
+ .Case("AS_LoopNest", Association::LoopNest)
+ .Case("AS_LoopSeq", Association::LoopSeq)
.Case("AS_None", Association::None)
.Case("AS_Separating", Association::Separating)
.Case("AS_FromLeaves", Association::FromLeaves)
@@ -777,13 +779,12 @@ static void generateGetDirectiveAssociation(const DirectiveLanguage &DirLang,
// Calculate the result using the following rules:
// x + x = x
// AS_None + x = x
- // AS_Block + AS_Loop = AS_Loop
+ // AS_Block + AS_Loop{Nest|Seq} = AS_Loop{Nest|Seq}
if (A == Association::None || A == B)
return B;
- if (A == Association::Block && B == Association::Loop)
+ if (A == Association::Block &&
+ (B == Association::LoopNest || B == Association::LoopSeq))
return B;
- if (A == Association::Loop && B == Association::Block)
- return A;
return Association::Invalid;
};
More information about the llvm-commits
mailing list