[clang] [llvm] [Frontend] Add leaf constructs and association to OpenMP/ACC directives (PR #83625)
Krzysztof Parzyszek via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 1 13:52:25 PST 2024
https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/83625
Add members "leafs" and "association" to .td describing OpenMP/ACC directives: "leafs" are the leaf constructs for composite/combined constructs, and "association" is the source language construct to which the directive applies (e.g. loop, block, etc.)
The tblgen-generated output then contains two additional functions
- getLeafConstructs(D), and
- getDirectiveAssociation(D) plus "enum class Association", all in namespaces "llvm::omp" and "llvm::acc".
Note: getLeafConstructs returns an empty sequence for a construct that is itself a leaf construct.
Use the new functions to simplify a few OpenMP-related functions in clang.
>From 544b309d77a7094d35794e574a1a1d12438021cd Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Tue, 16 Jan 2024 16:40:47 -0600
Subject: [PATCH] [Frontend] Add leaf constructs and association to OpenMP/ACC
directives
Add members "leafs" and "association" to .td describing OpenMP/ACC
directives: "leafs" are the leaf constructs for composite/combined
constructs, and "association" is the source language construct to
which the directive applies (e.g. loop, block, etc.)
The tblgen-generated output then contains two additional functions
- getLeafConstructs(D), and
- getDirectiveAssociation(D)
plus "enum class Association", all in namespaces "llvm::omp" and
"llvm::acc".
Note: getLeafConstructs returns an empty sequence for a construct
that is itself a leaf construct.
Use the new functions to simplify a few OpenMP-related functions
in clang.
---
clang/lib/Basic/OpenMPKinds.cpp | 130 +++-------
.../llvm/Frontend/Directive/DirectiveBase.td | 36 +++
llvm/include/llvm/Frontend/OpenACC/ACC.td | 27 +-
llvm/include/llvm/Frontend/OpenMP/OMP.td | 172 +++++++++++--
llvm/include/llvm/TableGen/DirectiveEmitter.h | 12 +
llvm/utils/TableGen/DirectiveEmitter.cpp | 236 +++++++++++++++++-
6 files changed, 491 insertions(+), 122 deletions(-)
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 6c31b0824eb8a4..dd1a096d178111 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -574,31 +574,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
}
bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) {
- return DKind == OMPD_simd || DKind == OMPD_for || DKind == OMPD_for_simd ||
- DKind == OMPD_parallel_for || DKind == OMPD_parallel_for_simd ||
- DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd ||
- DKind == OMPD_master_taskloop || DKind == OMPD_master_taskloop_simd ||
- DKind == OMPD_parallel_master_taskloop ||
- DKind == OMPD_parallel_master_taskloop_simd ||
- DKind == OMPD_masked_taskloop || DKind == OMPD_masked_taskloop_simd ||
- DKind == OMPD_parallel_masked_taskloop || DKind == OMPD_distribute ||
- DKind == OMPD_parallel_masked_taskloop_simd ||
- DKind == OMPD_target_parallel_for ||
- DKind == OMPD_distribute_parallel_for ||
- DKind == OMPD_distribute_parallel_for_simd ||
- DKind == OMPD_distribute_simd ||
- DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd ||
- DKind == OMPD_teams_distribute ||
- DKind == OMPD_teams_distribute_simd ||
- DKind == OMPD_teams_distribute_parallel_for_simd ||
- DKind == OMPD_teams_distribute_parallel_for ||
- DKind == OMPD_target_teams_distribute ||
- DKind == OMPD_target_teams_distribute_parallel_for ||
- DKind == OMPD_target_teams_distribute_parallel_for_simd ||
- DKind == OMPD_target_teams_distribute_simd || DKind == OMPD_tile ||
- DKind == OMPD_unroll || DKind == OMPD_loop ||
- DKind == OMPD_teams_loop || DKind == OMPD_target_teams_loop ||
- DKind == OMPD_parallel_loop || DKind == OMPD_target_parallel_loop;
+ return getDirectiveAssociation(DKind) == Association::Loop;
}
bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
@@ -619,44 +595,22 @@ bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
}
bool clang::isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind) {
- return DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd ||
- DKind == OMPD_master_taskloop || DKind == OMPD_master_taskloop_simd ||
- DKind == OMPD_parallel_master_taskloop ||
- DKind == OMPD_masked_taskloop || DKind == OMPD_masked_taskloop_simd ||
- DKind == OMPD_parallel_masked_taskloop ||
- DKind == OMPD_parallel_masked_taskloop_simd ||
- DKind == OMPD_parallel_master_taskloop_simd;
+ return DKind == OMPD_taskloop ||
+ llvm::is_contained(getLeafConstructs(DKind), OMPD_taskloop);
}
bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) {
- return DKind == OMPD_parallel || DKind == OMPD_parallel_for ||
- DKind == OMPD_parallel_for_simd || DKind == OMPD_parallel_sections ||
- DKind == OMPD_target_parallel || DKind == OMPD_target_parallel_for ||
- DKind == OMPD_distribute_parallel_for ||
- DKind == OMPD_distribute_parallel_for_simd ||
- DKind == OMPD_target_parallel_for_simd ||
- DKind == OMPD_teams_distribute_parallel_for ||
- DKind == OMPD_teams_distribute_parallel_for_simd ||
- DKind == OMPD_target_teams_distribute_parallel_for ||
- DKind == OMPD_target_teams_distribute_parallel_for_simd ||
- DKind == OMPD_parallel_master || DKind == OMPD_parallel_masked ||
- DKind == OMPD_parallel_master_taskloop ||
- DKind == OMPD_parallel_master_taskloop_simd ||
- DKind == OMPD_parallel_masked_taskloop ||
- DKind == OMPD_parallel_masked_taskloop_simd ||
- DKind == OMPD_parallel_loop || DKind == OMPD_target_parallel_loop ||
- DKind == OMPD_teams_loop;
+ if (DKind == OMPD_parallel_workshare)
+ return false;
+ if (DKind == OMPD_teams_loop)
+ return true;
+ return DKind == OMPD_parallel ||
+ llvm::is_contained(getLeafConstructs(DKind), OMPD_parallel);
}
bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) {
- return DKind == OMPD_target || DKind == OMPD_target_parallel ||
- DKind == OMPD_target_parallel_for ||
- DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd ||
- DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute ||
- DKind == OMPD_target_teams_distribute_parallel_for ||
- DKind == OMPD_target_teams_distribute_parallel_for_simd ||
- DKind == OMPD_target_teams_distribute_simd ||
- DKind == OMPD_target_teams_loop || DKind == OMPD_target_parallel_loop;
+ return DKind == OMPD_target ||
+ llvm::is_contained(getLeafConstructs(DKind), OMPD_target);
}
bool clang::isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind) {
@@ -665,60 +619,44 @@ bool clang::isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind) {
}
bool clang::isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind) {
- return DKind == OMPD_teams || DKind == OMPD_teams_distribute ||
- DKind == OMPD_teams_distribute_simd ||
- DKind == OMPD_teams_distribute_parallel_for_simd ||
- DKind == OMPD_teams_distribute_parallel_for ||
- DKind == OMPD_teams_loop;
+ if (DKind == OMPD_teams)
+ return true;
+ auto leafs = getLeafConstructs(DKind);
+ return !leafs.empty() && leafs.front() == OMPD_teams;
}
bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) {
- return isOpenMPNestingTeamsDirective(DKind) || DKind == OMPD_target_teams ||
- DKind == OMPD_target_teams_distribute ||
- DKind == OMPD_target_teams_distribute_parallel_for ||
- DKind == OMPD_target_teams_distribute_parallel_for_simd ||
- DKind == OMPD_target_teams_distribute_simd ||
- DKind == OMPD_target_teams_loop;
+ return DKind == OMPD_teams ||
+ llvm::is_contained(getLeafConstructs(DKind), OMPD_teams);
}
bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) {
- return DKind == OMPD_simd || DKind == OMPD_for_simd ||
- DKind == OMPD_parallel_for_simd || DKind == OMPD_taskloop_simd ||
- DKind == OMPD_master_taskloop_simd ||
- DKind == OMPD_masked_taskloop_simd ||
- DKind == OMPD_parallel_master_taskloop_simd ||
- DKind == OMPD_parallel_masked_taskloop_simd ||
- DKind == OMPD_distribute_parallel_for_simd ||
- DKind == OMPD_distribute_simd || DKind == OMPD_target_simd ||
- DKind == OMPD_teams_distribute_simd ||
- DKind == OMPD_teams_distribute_parallel_for_simd ||
- DKind == OMPD_target_teams_distribute_parallel_for_simd ||
- DKind == OMPD_target_teams_distribute_simd ||
- DKind == OMPD_target_parallel_for_simd;
+ // Avoid OMPD_declare_simd
+ if (DKind == OMPD_end_do_simd ||
+ getDirectiveAssociation(DKind) != Association::Loop)
+ return false;
+
+ return DKind == OMPD_simd ||
+ llvm::is_contained(getLeafConstructs(DKind), OMPD_simd);
}
bool clang::isOpenMPNestingDistributeDirective(OpenMPDirectiveKind Kind) {
- return Kind == OMPD_distribute || Kind == OMPD_distribute_parallel_for ||
- Kind == OMPD_distribute_parallel_for_simd ||
- Kind == OMPD_distribute_simd;
- // TODO add next directives.
+ if (Kind == OMPD_distribute)
+ return true;
+ auto leafs = getLeafConstructs(Kind);
+ return !leafs.empty() && leafs.front() == OMPD_distribute;
}
bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) {
- return isOpenMPNestingDistributeDirective(Kind) ||
- Kind == OMPD_teams_distribute || Kind == OMPD_teams_distribute_simd ||
- Kind == OMPD_teams_distribute_parallel_for_simd ||
- Kind == OMPD_teams_distribute_parallel_for ||
- Kind == OMPD_target_teams_distribute ||
- Kind == OMPD_target_teams_distribute_parallel_for ||
- Kind == OMPD_target_teams_distribute_parallel_for_simd ||
- Kind == OMPD_target_teams_distribute_simd;
+ return Kind == OMPD_distribute ||
+ llvm::is_contained(getLeafConstructs(Kind), OMPD_distribute);
}
bool clang::isOpenMPGenericLoopDirective(OpenMPDirectiveKind Kind) {
- return Kind == OMPD_loop || Kind == OMPD_teams_loop ||
- Kind == OMPD_target_teams_loop || Kind == OMPD_parallel_loop ||
- Kind == OMPD_target_parallel_loop;
+ if (Kind == OMPD_loop)
+ return true;
+ auto leafs = getLeafConstructs(Kind);
+ return !leafs.empty() && leafs.back() == OMPD_loop;
}
bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
diff --git a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
index 31578710365b21..4d5201aabe8afb 100644
--- a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
+++ b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
@@ -127,6 +127,35 @@ class VersionedClause<Clause c, int min = 1, int max = 0x7FFFFFFF> {
int maxVersion = max;
}
+// Kinds of directive associations.
+class Association<string n> {
+ string name = n; // Name of the enum value in enum class Association.
+}
+// All of the AS_Xyz names are recognized by TableGen in order to calculate
+// the association in the AS_FromLeafs case.
+def AS_None : Association<"None"> {} // No association
+def AS_Block : Association<"Block"> {} // Block (incl. single
+ // statement)
+def AS_Declaration : Association<"Declaration"> {} // Declaration
+def AS_Delimited : Association<"Delimited"> {} // Region delimited with
+ // begin/end
+def AS_Loop : Association<"Loop"> {} // Loop
+def AS_Separating : Association<"Separating"> {} // Separates parts of a
+ // construct
+
+def AS_FromLeafs : Association<"FromLeafs"> {} // See below
+// AS_FromLeafs can be used for combined/composite directives, and the actual
+// association will be computed based on associations of the leaf constructs:
+// (x + y) + z = x + (y + z)
+// x + y = y + x
+// x + x = x
+// AS_None + x = x
+// AS_Block + AS_Loop = AS_Loop
+// Other combinations are not allowed.
+// This association is not valid for leaf constructs.
+// The name "AS_FromLeafs" is recognized by TableGen, and there is no enum
+// generated for it.
+
// Information about a specific directive.
class Directive<string d> {
// Name of the directive. Can be composite directive sepearted by whitespace.
@@ -152,6 +181,13 @@ class Directive<string d> {
// List of clauses that are required.
list<VersionedClause> requiredClauses = [];
+ // List of leaf constituent directives in the order in which they appear
+ // in the combined/composite directive.
+ list<Directive> leafs = [];
+
// Set directive used by default when unknown.
bit isDefault = false;
+
+ // What the directive is associated with.
+ Association association = AS_FromLeafs;
}
diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td
index 0dbd934d83f064..3c8cc1af0518b1 100644
--- a/llvm/include/llvm/Frontend/OpenACC/ACC.td
+++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td
@@ -266,7 +266,9 @@ def ACCC_Unknown : Clause<"unknown"> {
//===----------------------------------------------------------------------===//
// 2.12
-def ACC_Atomic : Directive<"atomic"> {}
+def ACC_Atomic : Directive<"atomic"> {
+ let association = AS_Block;
+}
// 2.6.5
def ACC_Data : Directive<"data"> {
@@ -290,6 +292,7 @@ def ACC_Data : Directive<"data"> {
VersionedClause<ACCC_NoCreate>,
VersionedClause<ACCC_Present>
];
+ let association = AS_Block;
}
// 2.13
@@ -304,6 +307,7 @@ def ACC_Declare : Directive<"declare"> {
VersionedClause<ACCC_DeviceResident>,
VersionedClause<ACCC_Link>
];
+ let association = AS_None;
}
// 2.5.3
@@ -329,6 +333,7 @@ def ACC_Kernels : Directive<"kernels"> {
VersionedClause<ACCC_Self>,
VersionedClause<ACCC_VectorLength>
];
+ let association = AS_Block;
}
// 2.5.1
@@ -357,6 +362,7 @@ def ACC_Parallel : Directive<"parallel"> {
VersionedClause<ACCC_If>,
VersionedClause<ACCC_Self>
];
+ let association = AS_Block;
}
// 2.5.2
@@ -384,6 +390,7 @@ def ACC_Serial : Directive<"serial"> {
VersionedClause<ACCC_If>,
VersionedClause<ACCC_Self>
];
+ let association = AS_Block;
}
// 2.9
@@ -403,10 +410,13 @@ def ACC_Loop : Directive<"loop"> {
VersionedClause<ACCC_Independent>,
VersionedClause<ACCC_Seq>
];
+ let association = AS_Loop;
}
// 2.10
-def ACC_Cache : Directive<"cache"> {}
+def ACC_Cache : Directive<"cache"> {
+ let association = AS_None;
+}
// 2.14.1
def ACC_Init : Directive<"init"> {
@@ -415,6 +425,7 @@ def ACC_Init : Directive<"init"> {
VersionedClause<ACCC_DeviceType>,
VersionedClause<ACCC_If>
];
+ let association = AS_None;
}
// 2.15.1
@@ -430,6 +441,7 @@ def ACC_Routine : Directive<"routine"> {
let allowedOnceClauses = [
VersionedClause<ACCC_NoHost>
];
+ let association = AS_Declaration;
}
// 2.14.3
@@ -448,6 +460,7 @@ def ACC_Set : Directive<"set"> {
VersionedClause<ACCC_DeviceNum>,
VersionedClause<ACCC_DeviceType>
];
+ let association = AS_None;
}
// 2.14.2
@@ -457,6 +470,7 @@ def ACC_Shutdown : Directive<"shutdown"> {
VersionedClause<ACCC_DeviceType>,
VersionedClause<ACCC_If>
];
+ let association = AS_None;
}
// 2.14.4
@@ -475,6 +489,7 @@ def ACC_Update : Directive<"update"> {
VersionedClause<ACCC_Host>,
VersionedClause<ACCC_Self>
];
+ let association = AS_None;
}
// 2.16.3
@@ -483,6 +498,7 @@ def ACC_Wait : Directive<"wait"> {
VersionedClause<ACCC_Async>,
VersionedClause<ACCC_If>
];
+ let association = AS_None;
}
// 2.14.6
@@ -499,6 +515,7 @@ def ACC_EnterData : Directive<"enter data"> {
VersionedClause<ACCC_Create>,
VersionedClause<ACCC_Copyin>
];
+ let association = AS_None;
}
// 2.14.7
@@ -516,6 +533,7 @@ def ACC_ExitData : Directive<"exit data"> {
VersionedClause<ACCC_Delete>,
VersionedClause<ACCC_Detach>
];
+ let association = AS_None;
}
// 2.8
@@ -527,6 +545,7 @@ def ACC_HostData : Directive<"host_data"> {
let requiredClauses = [
VersionedClause<ACCC_UseDevice>
];
+ let association = AS_Block;
}
// 2.11
@@ -564,6 +583,7 @@ def ACC_KernelsLoop : Directive<"kernels loop"> {
VersionedClause<ACCC_Independent>,
VersionedClause<ACCC_Seq>
];
+ let leafs = [ACC_Kernels, ACC_Loop];
}
// 2.11
@@ -602,6 +622,7 @@ def ACC_ParallelLoop : Directive<"parallel loop"> {
VersionedClause<ACCC_Independent>,
VersionedClause<ACCC_Seq>
];
+ let leafs = [ACC_Parallel, ACC_Loop];
}
// 2.11
@@ -637,8 +658,10 @@ def ACC_SerialLoop : Directive<"serial loop"> {
VersionedClause<ACCC_Independent>,
VersionedClause<ACCC_Seq>
];
+ let leafs = [ACC_Serial, ACC_Loop];
}
def ACC_Unknown : Directive<"unknown"> {
let isDefault = true;
+ let association = AS_None;
}
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 77d207f2b10a83..fecc49e888a454 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -463,7 +463,9 @@ def OMPC_OMX_Bare : Clause<"ompx_bare"> {
// Definition of OpenMP directives
//===----------------------------------------------------------------------===//
-def OMP_ThreadPrivate : Directive<"threadprivate"> {}
+def OMP_ThreadPrivate : Directive<"threadprivate"> {
+ let association = AS_None;
+}
def OMP_Parallel : Directive<"parallel"> {
let allowedClauses = [
VersionedClause<OMPC_Private>,
@@ -480,6 +482,7 @@ def OMP_Parallel : Directive<"parallel"> {
VersionedClause<OMPC_NumThreads>,
VersionedClause<OMPC_ProcBind>,
];
+ let association = AS_Block;
}
def OMP_Task : Directive<"task"> {
let allowedClauses = [
@@ -500,6 +503,7 @@ def OMP_Task : Directive<"task"> {
VersionedClause<OMPC_Final>,
VersionedClause<OMPC_Priority>
];
+ let association = AS_Block;
}
def OMP_Simd : Directive<"simd"> {
let allowedClauses = [
@@ -518,17 +522,20 @@ def OMP_Simd : Directive<"simd"> {
VersionedClause<OMPC_If, 50>,
VersionedClause<OMPC_Order, 50>
];
+ let association = AS_Loop;
}
def OMP_Tile : Directive<"tile"> {
let allowedOnceClauses = [
VersionedClause<OMPC_Sizes, 51>,
];
+ let association = AS_Loop;
}
def OMP_Unroll : Directive<"unroll"> {
let allowedOnceClauses = [
VersionedClause<OMPC_Full, 51>,
VersionedClause<OMPC_Partial, 51>,
];
+ let association = AS_Loop;
}
def OMP_For : Directive<"for"> {
let allowedClauses = [
@@ -544,6 +551,7 @@ def OMP_For : Directive<"for"> {
VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Order, 50>
];
+ let association = AS_Loop;
}
def OMP_Do : Directive<"do"> {
let allowedClauses = [
@@ -560,6 +568,7 @@ def OMP_Do : Directive<"do"> {
VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_Order, 50>
];
+ let association = AS_Loop;
}
def OMP_Sections : Directive<"sections"> {
let allowedClauses = [
@@ -570,8 +579,11 @@ def OMP_Sections : Directive<"sections"> {
VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_Allocate>
];
+ let association = AS_Block;
+}
+def OMP_Section : Directive<"section"> {
+ let association = AS_Separating;
}
-def OMP_Section : Directive<"section"> {}
def OMP_Single : Directive<"single"> {
let allowedClauses = [
VersionedClause<OMPC_Private>,
@@ -580,33 +592,44 @@ def OMP_Single : Directive<"single"> {
VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_Allocate>
];
+ let association = AS_Block;
+}
+def OMP_Master : Directive<"master"> {
+ let association = AS_Block;
}
-def OMP_Master : Directive<"master"> {}
def OMP_Critical : Directive<"critical"> {
let allowedClauses = [
VersionedClause<OMPC_Hint>
];
+ let association = AS_Block;
+}
+def OMP_TaskYield : Directive<"taskyield"> {
+ let association = AS_None;
+}
+def OMP_Barrier : Directive<"barrier"> {
+ let association = AS_None;
}
-def OMP_TaskYield : Directive<"taskyield"> {}
-def OMP_Barrier : Directive<"barrier"> {}
def OMP_Error : Directive<"error"> {
let allowedClauses = [
VersionedClause<OMPC_At, 51>,
VersionedClause<OMPC_Severity, 51>,
VersionedClause<OMPC_Message, 51>
];
+ let association = AS_None;
}
def OMP_TaskWait : Directive<"taskwait"> {
let allowedClauses = [
VersionedClause<OMPC_Depend, 50>,
VersionedClause<OMPC_NoWait, 51>
];
+ let association = AS_None;
}
def OMP_TaskGroup : Directive<"taskgroup"> {
let allowedClauses = [
VersionedClause<OMPC_TaskReduction, 50>,
VersionedClause<OMPC_Allocate, 50>
];
+ let association = AS_Block;
}
def OMP_Flush : Directive<"flush"> {
let allowedOnceClauses = [
@@ -617,6 +640,7 @@ def OMP_Flush : Directive<"flush"> {
// OMPKinds.def.
VersionedClause<OMPC_Flush>
];
+ let association = AS_None;
}
def OMP_Ordered : Directive<"ordered"> {
let allowedClauses = [
@@ -627,6 +651,8 @@ def OMP_Ordered : Directive<"ordered"> {
VersionedClause<OMPC_Threads>,
VersionedClause<OMPC_Simd>
];
+ let association = AS_None;
+ // There is also a block-associated "ordered" directive.
}
def OMP_Atomic : Directive<"atomic"> {
let allowedClauses = [
@@ -646,6 +672,7 @@ def OMP_Atomic : Directive<"atomic"> {
VersionedClause<OMPC_Fail, 51>,
VersionedClause<OMPC_Weak, 51>
];
+ let association = AS_Block;
}
def OMP_Target : Directive<"target"> {
let allowedClauses = [
@@ -669,6 +696,7 @@ def OMP_Target : Directive<"target"> {
VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_OMPX_DynCGroupMem>,
];
+ let association = AS_Block;
}
def OMP_Teams : Directive<"teams"> {
let allowedClauses = [
@@ -685,11 +713,13 @@ def OMP_Teams : Directive<"teams"> {
VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_ThreadLimit>
];
+ let association = AS_Block;
}
def OMP_Cancel : Directive<"cancel"> {
let allowedOnceClauses = [
VersionedClause<OMPC_If>
];
+ let association = AS_None;
}
def OMP_Requires : Directive<"requires"> {
let allowedOnceClauses = [
@@ -707,8 +737,11 @@ def OMP_Requires : Directive<"requires"> {
VersionedClause<OMPC_DynamicAllocators>,
VersionedClause<OMPC_AtomicDefaultMemOrder>
];
+ let association = AS_None;
+}
+def OMP_Nothing : Directive<"nothing"> {
+ let association = AS_None;
}
-def OMP_Nothing : Directive<"nothing"> {}
def OMP_TargetData : Directive<"target data"> {
let allowedOnceClauses = [
VersionedClause<OMPC_Device>,
@@ -719,6 +752,7 @@ def OMP_TargetData : Directive<"target data"> {
VersionedClause<OMPC_UseDevicePtr>,
VersionedClause<OMPC_UseDeviceAddr, 50>
];
+ let association = AS_Block;
}
def OMP_TargetEnterData : Directive<"target enter data"> {
let allowedClauses = [
@@ -732,6 +766,7 @@ def OMP_TargetEnterData : Directive<"target enter data"> {
let requiredClauses = [
VersionedClause<OMPC_Map>
];
+ let association = AS_None;
}
def OMP_TargetExitData : Directive<"target exit data"> {
let allowedClauses = [
@@ -745,6 +780,7 @@ def OMP_TargetExitData : Directive<"target exit data"> {
let requiredClauses = [
VersionedClause<OMPC_Map>
];
+ let association = AS_None;
}
def OMP_TargetParallel : Directive<"target parallel"> {
let allowedClauses = [
@@ -771,6 +807,7 @@ def OMP_TargetParallel : Directive<"target parallel"> {
VersionedClause<OMPC_OMPX_DynCGroupMem>,
VersionedClause<OMPC_ThreadLimit, 51>,
];
+ let leafs = [OMP_Target, OMP_Parallel];
}
def OMP_TargetParallelFor : Directive<"target parallel for"> {
let allowedClauses = [
@@ -803,6 +840,7 @@ def OMP_TargetParallelFor : Directive<"target parallel for"> {
VersionedClause<OMPC_OMPX_DynCGroupMem>,
VersionedClause<OMPC_ThreadLimit, 51>,
];
+ let leafs = [OMP_Target, OMP_Parallel, OMP_For];
}
def OMP_TargetParallelDo : Directive<"target parallel do"> {
let allowedClauses = [
@@ -833,6 +871,7 @@ def OMP_TargetParallelDo : Directive<"target parallel do"> {
VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Target, OMP_Parallel, OMP_Do];
}
def OMP_TargetUpdate : Directive<"target update"> {
let allowedClauses = [
@@ -845,6 +884,13 @@ def OMP_TargetUpdate : Directive<"target update"> {
VersionedClause<OMPC_If>,
VersionedClause<OMPC_NoWait>
];
+ let association = AS_None;
+}
+def OMP_masked : Directive<"masked"> {
+ let allowedOnceClauses = [
+ VersionedClause<OMPC_Filter>
+ ];
+ let association = AS_Block;
}
def OMP_ParallelFor : Directive<"parallel for"> {
let allowedClauses = [
@@ -866,6 +912,7 @@ def OMP_ParallelFor : Directive<"parallel for"> {
VersionedClause<OMPC_Order, 50>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Parallel, OMP_For];
}
def OMP_ParallelDo : Directive<"parallel do"> {
let allowedClauses = [
@@ -887,6 +934,7 @@ def OMP_ParallelDo : Directive<"parallel do"> {
VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Parallel, OMP_Do];
}
def OMP_ParallelForSimd : Directive<"parallel for simd"> {
let allowedClauses = [
@@ -912,6 +960,7 @@ def OMP_ParallelForSimd : Directive<"parallel for simd"> {
VersionedClause<OMPC_Order, 50>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Parallel, OMP_For, OMP_Simd];
}
def OMP_ParallelDoSimd : Directive<"parallel do simd"> {
let allowedClauses = [
@@ -938,6 +987,7 @@ def OMP_ParallelDoSimd : Directive<"parallel do simd"> {
VersionedClause<OMPC_SimdLen>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Parallel, OMP_Do, OMP_Simd];
}
def OMP_ParallelMaster : Directive<"parallel master"> {
let allowedClauses = [
@@ -953,6 +1003,7 @@ def OMP_ParallelMaster : Directive<"parallel master"> {
VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Parallel, OMP_Master];
}
def OMP_ParallelMasked : Directive<"parallel masked"> {
let allowedClauses = [
@@ -969,6 +1020,7 @@ def OMP_ParallelMasked : Directive<"parallel masked"> {
VersionedClause<OMPC_Filter>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Parallel, OMP_masked];
}
def OMP_ParallelSections : Directive<"parallel sections"> {
let allowedClauses = [
@@ -987,6 +1039,7 @@ def OMP_ParallelSections : Directive<"parallel sections"> {
VersionedClause<OMPC_If>,
VersionedClause<OMPC_NumThreads>
];
+ let leafs = [OMP_Parallel, OMP_Sections];
}
def OMP_ForSimd : Directive<"for simd"> {
let allowedClauses = [
@@ -1007,6 +1060,7 @@ def OMP_ForSimd : Directive<"for simd"> {
VersionedClause<OMPC_NonTemporal, 50>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_For, OMP_Simd];
}
def OMP_DoSimd : Directive<"do simd"> {
let allowedClauses = [
@@ -1027,13 +1081,19 @@ def OMP_DoSimd : Directive<"do simd"> {
VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Do, OMP_Simd];
+}
+def OMP_CancellationPoint : Directive<"cancellation point"> {
+ let association = AS_None;
+}
+def OMP_DeclareReduction : Directive<"declare reduction"> {
+ let association = AS_None;
}
-def OMP_CancellationPoint : Directive<"cancellation point"> {}
-def OMP_DeclareReduction : Directive<"declare reduction"> {}
def OMP_DeclareMapper : Directive<"declare mapper"> {
let allowedClauses = [
VersionedClause<OMPC_Map>
];
+ let association = AS_None;
}
def OMP_DeclareSimd : Directive<"declare simd"> {
let allowedClauses = [
@@ -1048,6 +1108,7 @@ def OMP_DeclareSimd : Directive<"declare simd"> {
VersionedClause<OMPC_Inbranch>,
VersionedClause<OMPC_Notinbranch>
];
+ let association = AS_Declaration;
}
def OMP_TaskLoop : Directive<"taskloop"> {
let allowedClauses = [
@@ -1073,6 +1134,7 @@ def OMP_TaskLoop : Directive<"taskloop"> {
VersionedClause<OMPC_GrainSize>,
VersionedClause<OMPC_NumTasks>
];
+ let association = AS_Loop;
}
def OMP_TaskLoopSimd : Directive<"taskloop simd"> {
let allowedClauses = [
@@ -1104,6 +1166,7 @@ def OMP_TaskLoopSimd : Directive<"taskloop simd"> {
VersionedClause<OMPC_GrainSize>,
VersionedClause<OMPC_NumTasks>
];
+ let leafs = [OMP_TaskLoop, OMP_Simd];
}
def OMP_Distribute : Directive<"distribute"> {
let allowedClauses = [
@@ -1116,6 +1179,7 @@ def OMP_Distribute : Directive<"distribute"> {
VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_DistSchedule>
];
+ let association = AS_Loop;
}
def OMP_BeginDeclareTarget : Directive<"begin declare target"> {
let allowedClauses = [
@@ -1124,6 +1188,7 @@ def OMP_BeginDeclareTarget : Directive<"begin declare target"> {
VersionedClause<OMPC_DeviceType>,
VersionedClause<OMPC_Indirect>
];
+ let association = AS_Delimited;
}
def OMP_DeclareTarget : Directive<"declare target"> {
let allowedClauses = [
@@ -1135,8 +1200,11 @@ def OMP_DeclareTarget : Directive<"declare target"> {
let allowedOnceClauses = [
VersionedClause<OMPC_DeviceType, 50>
];
+ let association = AS_None;
+}
+def OMP_EndDeclareTarget : Directive<"end declare target"> {
+ let association = AS_Delimited;
}
-def OMP_EndDeclareTarget : Directive<"end declare target"> {}
def OMP_DistributeParallelFor : Directive<"distribute parallel for"> {
let allowedClauses = [
VersionedClause<OMPC_FirstPrivate>,
@@ -1156,6 +1224,7 @@ def OMP_DistributeParallelFor : Directive<"distribute parallel for"> {
VersionedClause<OMPC_Order, 50>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Distribute, OMP_Parallel, OMP_For];
}
def OMP_DistributeParallelDo : Directive<"distribute parallel do"> {
let allowedClauses = [
@@ -1179,6 +1248,7 @@ def OMP_DistributeParallelDo : Directive<"distribute parallel do"> {
VersionedClause<OMPC_Ordered>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Distribute, OMP_Parallel, OMP_Do];
}
def OMP_DistributeParallelForSimd : Directive<"distribute parallel for simd"> {
let allowedClauses = [
@@ -1204,6 +1274,7 @@ def OMP_DistributeParallelForSimd : Directive<"distribute parallel for simd"> {
VersionedClause<OMPC_Order, 50>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Distribute, OMP_Parallel, OMP_For, OMP_Simd];
}
def OMP_DistributeParallelDoSimd : Directive<"distribute parallel do simd"> {
let allowedClauses = [
@@ -1228,6 +1299,7 @@ def OMP_DistributeParallelDoSimd : Directive<"distribute parallel do simd"> {
VersionedClause<OMPC_NonTemporal>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Distribute, OMP_Parallel, OMP_Do, OMP_Simd];
}
def OMP_DistributeSimd : Directive<"distribute simd"> {
let allowedClauses = [
@@ -1254,6 +1326,7 @@ def OMP_DistributeSimd : Directive<"distribute simd"> {
VersionedClause<OMPC_SimdLen>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Distribute, OMP_Simd];
}
def OMP_TargetParallelForSimd : Directive<"target parallel for simd"> {
@@ -1291,6 +1364,7 @@ def OMP_TargetParallelForSimd : Directive<"target parallel for simd"> {
VersionedClause<OMPC_OMPX_DynCGroupMem>,
VersionedClause<OMPC_ThreadLimit, 51>,
];
+ let leafs = [OMP_Target, OMP_Parallel, OMP_For, OMP_Simd];
}
def OMP_TargetParallelDoSimd : Directive<"target parallel do simd"> {
let allowedClauses = [
@@ -1322,6 +1396,7 @@ def OMP_TargetParallelDoSimd : Directive<"target parallel do simd"> {
VersionedClause<OMPC_Order, 50>,
VersionedClause<OMPC_UsesAllocators>
];
+ let leafs = [OMP_Target, OMP_Parallel, OMP_Do, OMP_Simd];
}
def OMP_TargetSimd : Directive<"target simd"> {
let allowedClauses = [
@@ -1356,6 +1431,7 @@ def OMP_TargetSimd : Directive<"target simd"> {
VersionedClause<OMPC_Order, 50>,
VersionedClause<OMPC_ThreadLimit, 51>,
];
+ let leafs = [OMP_Target, OMP_Simd];
}
def OMP_TeamsDistribute : Directive<"teams distribute"> {
let allowedClauses = [
@@ -1375,6 +1451,7 @@ def OMP_TeamsDistribute : Directive<"teams distribute"> {
let allowedOnceClauses = [
VersionedClause<OMPC_If>
];
+ let leafs = [OMP_Teams, OMP_Distribute];
}
def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> {
let allowedClauses = [
@@ -1400,6 +1477,7 @@ def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> {
VersionedClause<OMPC_ThreadLimit>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Teams, OMP_Distribute, OMP_Simd];
}
def OMP_TeamsDistributeParallelForSimd :
@@ -1428,6 +1506,7 @@ def OMP_TeamsDistributeParallelForSimd :
VersionedClause<OMPC_Order, 50>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For, OMP_Simd];
}
def OMP_TeamsDistributeParallelDoSimd :
Directive<"teams distribute parallel do simd"> {
@@ -1456,6 +1535,7 @@ def OMP_TeamsDistributeParallelDoSimd :
VersionedClause<OMPC_SimdLen>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_Do, OMP_Simd];
}
def OMP_TeamsDistributeParallelFor :
Directive<"teams distribute parallel for"> {
@@ -1479,6 +1559,7 @@ def OMP_TeamsDistributeParallelFor :
VersionedClause<OMPC_Order, 50>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For];
}
def OMP_TeamsDistributeParallelDo :
Directive<"teams distribute parallel do"> {
@@ -1505,6 +1586,7 @@ let allowedOnceClauses = [
VersionedClause<OMPC_Schedule>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_Do];
}
def OMP_TargetTeams : Directive<"target teams"> {
let allowedClauses = [
@@ -1532,6 +1614,7 @@ def OMP_TargetTeams : Directive<"target teams"> {
VersionedClause<OMPC_OMPX_DynCGroupMem>,
VersionedClause<OMPC_OMX_Bare>,
];
+ let leafs = [OMP_Target, OMP_Teams];
}
def OMP_TargetTeamsDistribute : Directive<"target teams distribute"> {
let allowedClauses = [
@@ -1560,6 +1643,7 @@ def OMP_TargetTeamsDistribute : Directive<"target teams distribute"> {
VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_OMPX_DynCGroupMem>,
];
+ let leafs = [OMP_Target, OMP_Teams, OMP_Distribute];
}
def OMP_TargetTeamsDistributeParallelFor :
@@ -1594,6 +1678,7 @@ def OMP_TargetTeamsDistributeParallelFor :
let allowedOnceClauses = [
VersionedClause<OMPC_OMPX_DynCGroupMem>,
];
+ let leafs = [OMP_Target, OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For];
}
def OMP_TargetTeamsDistributeParallelDo :
Directive<"target teams distribute parallel do"> {
@@ -1628,6 +1713,7 @@ def OMP_TargetTeamsDistributeParallelDo :
VersionedClause<OMPC_Schedule>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Target, OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_Do];
}
def OMP_TargetTeamsDistributeParallelForSimd :
Directive<"target teams distribute parallel for simd"> {
@@ -1666,6 +1752,7 @@ def OMP_TargetTeamsDistributeParallelForSimd :
let allowedOnceClauses = [
VersionedClause<OMPC_OMPX_DynCGroupMem>,
];
+ let leafs = [OMP_Target, OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For, OMP_Simd];
}
def OMP_TargetTeamsDistributeParallelDoSimd :
Directive<"target teams distribute parallel do simd"> {
@@ -1704,6 +1791,7 @@ def OMP_TargetTeamsDistributeParallelDoSimd :
VersionedClause<OMPC_SimdLen>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Target, OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_Do, OMP_Simd];
}
def OMP_TargetTeamsDistributeSimd :
Directive<"target teams distribute simd"> {
@@ -1738,17 +1826,20 @@ def OMP_TargetTeamsDistributeSimd :
VersionedClause<OMPC_OMPX_DynCGroupMem>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Target, OMP_Teams, OMP_Distribute, OMP_Simd];
}
def OMP_Allocate : Directive<"allocate"> {
let allowedOnceClauses = [
VersionedClause<OMPC_Allocator>,
VersionedClause<OMPC_Align, 51>
];
+ let association = AS_None;
}
def OMP_Allocators : Directive<"allocators"> {
let allowedClauses = [
VersionedClause<OMPC_Allocate>
];
+ let association = AS_Block;
}
def OMP_DeclareVariant : Directive<"declare variant"> {
let allowedClauses = [
@@ -1758,6 +1849,7 @@ def OMP_DeclareVariant : Directive<"declare variant"> {
VersionedClause<OMPC_AdjustArgs, 51>,
VersionedClause<OMPC_AppendArgs, 51>
];
+ let association = AS_Declaration;
}
def OMP_MasterTaskloop : Directive<"master taskloop"> {
let allowedClauses = [
@@ -1779,6 +1871,7 @@ def OMP_MasterTaskloop : Directive<"master taskloop"> {
VersionedClause<OMPC_InReduction>,
VersionedClause<OMPC_Allocate>
];
+ let leafs = [OMP_Master, OMP_TaskLoop];
}
def OMP_MaskedTaskloop : Directive<"masked taskloop"> {
let allowedClauses = [
@@ -1801,6 +1894,7 @@ def OMP_MaskedTaskloop : Directive<"masked taskloop"> {
VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Filter>
];
+ let leafs = [OMP_masked, OMP_TaskLoop];
}
def OMP_ParallelMasterTaskloop :
Directive<"parallel master taskloop"> {
@@ -1826,6 +1920,7 @@ def OMP_ParallelMasterTaskloop :
VersionedClause<OMPC_Copyin>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Parallel, OMP_Master, OMP_TaskLoop];
}
def OMP_ParallelMaskedTaskloop :
Directive<"parallel masked taskloop"> {
@@ -1852,6 +1947,7 @@ def OMP_ParallelMaskedTaskloop :
VersionedClause<OMPC_Filter>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Parallel, OMP_masked, OMP_TaskLoop];
}
def OMP_MasterTaskloopSimd : Directive<"master taskloop simd"> {
let allowedClauses = [
@@ -1879,6 +1975,7 @@ def OMP_MasterTaskloopSimd : Directive<"master taskloop simd"> {
VersionedClause<OMPC_NonTemporal, 50>,
VersionedClause<OMPC_Order, 50>
];
+ let leafs = [OMP_Master, OMP_TaskLoop, OMP_Simd];
}
def OMP_MaskedTaskloopSimd : Directive<"masked taskloop simd"> {
let allowedClauses = [
@@ -1907,6 +2004,7 @@ def OMP_MaskedTaskloopSimd : Directive<"masked taskloop simd"> {
VersionedClause<OMPC_Order, 50>,
VersionedClause<OMPC_Filter>
];
+ let leafs = [OMP_masked, OMP_TaskLoop, OMP_Simd];
}
def OMP_ParallelMasterTaskloopSimd :
Directive<"parallel master taskloop simd"> {
@@ -1938,6 +2036,7 @@ def OMP_ParallelMasterTaskloopSimd :
VersionedClause<OMPC_Order, 50>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Parallel, OMP_Master, OMP_TaskLoop, OMP_Simd];
}
def OMP_ParallelMaskedTaskloopSimd :
Directive<"parallel masked taskloop simd"> {
@@ -1970,6 +2069,7 @@ def OMP_ParallelMaskedTaskloopSimd :
VersionedClause<OMPC_Filter>,
VersionedClause<OMPC_OMPX_Attribute>,
];
+ let leafs = [OMP_Parallel, OMP_masked, OMP_TaskLoop, OMP_Simd];
}
def OMP_Depobj : Directive<"depobj"> {
let allowedClauses = [
@@ -1980,18 +2080,30 @@ def OMP_Depobj : Directive<"depobj"> {
// OMPKinds.def.
VersionedClause<OMPC_Depobj, 50>
];
+ let association = AS_None;
}
def OMP_Scan : Directive<"scan"> {
let allowedClauses = [
VersionedClause<OMPC_Inclusive, 50>,
VersionedClause<OMPC_Exclusive, 50>
];
+ let association = AS_Separating;
+}
+def OMP_Assumes : Directive<"assumes"> {
+ let association = AS_None;
+}
+def OMP_BeginAssumes : Directive<"begin assumes"> {
+ let association = AS_Delimited;
+}
+def OMP_EndAssumes : Directive<"end assumes"> {
+ let association = AS_Delimited;
+}
+def OMP_BeginDeclareVariant : Directive<"begin declare variant"> {
+ let association = AS_Delimited;
+}
+def OMP_EndDeclareVariant : Directive<"end declare variant"> {
+ let association = AS_Delimited;
}
-def OMP_Assumes : Directive<"assumes"> {}
-def OMP_BeginAssumes : Directive<"begin assumes"> {}
-def OMP_EndAssumes : Directive<"end assumes"> {}
-def OMP_BeginDeclareVariant : Directive<"begin declare variant"> {}
-def OMP_EndDeclareVariant : Directive<"end declare variant"> {}
def OMP_scope : Directive<"scope"> {
let allowedClauses = [
VersionedClause<OMPC_Private, 51>,
@@ -2000,6 +2112,10 @@ def OMP_scope : Directive<"scope"> {
let allowedOnceClauses = [
VersionedClause<OMPC_NoWait, 51>
];
+ let association = AS_Block;
+}
+def OMP_Workshare : Directive<"workshare"> {
+ let association = AS_Block;
}
def OMP_ParallelWorkshare : Directive<"parallel workshare"> {
let allowedClauses = [
@@ -2016,22 +2132,29 @@ def OMP_ParallelWorkshare : Directive<"parallel workshare"> {
VersionedClause<OMPC_NumThreads>,
VersionedClause<OMPC_ProcBind>
];
+ let leafs = [OMP_Parallel, OMP_Workshare];
}
-def OMP_Workshare : Directive<"workshare"> {}
def OMP_EndDo : Directive<"end do"> {
let allowedOnceClauses = [
VersionedClause<OMPC_NoWait>
];
+ // Needed for association computation, since OMP_Do has it "from leafs".
+ let leafs = OMP_Do.leafs;
+ let association = OMP_Do.association;
}
def OMP_EndDoSimd : Directive<"end do simd"> {
let allowedOnceClauses = [
VersionedClause<OMPC_NoWait>
];
+ let leafs = OMP_DoSimd.leafs;
+ let association = OMP_DoSimd.association;
}
def OMP_EndSections : Directive<"end sections"> {
let allowedOnceClauses = [
VersionedClause<OMPC_NoWait>
];
+ let leafs = OMP_Sections.leafs;
+ let association = OMP_Sections.association;
}
def OMP_EndSingle : Directive<"end single"> {
let allowedClauses = [
@@ -2040,11 +2163,15 @@ def OMP_EndSingle : Directive<"end single"> {
let allowedOnceClauses = [
VersionedClause<OMPC_NoWait>
];
+ let leafs = OMP_Single.leafs;
+ let association = OMP_Single.association;
}
def OMP_EndWorkshare : Directive<"end workshare"> {
let allowedClauses = [
VersionedClause<OMPC_NoWait>
];
+ let leafs = OMP_Workshare.leafs;
+ let association = OMP_Workshare.association;
}
def OMP_interop : Directive<"interop"> {
let allowedClauses = [
@@ -2055,6 +2182,7 @@ def OMP_interop : Directive<"interop"> {
VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_Use>,
];
+ let association = AS_None;
}
def OMP_dispatch : Directive<"dispatch"> {
let allowedClauses = [
@@ -2066,11 +2194,7 @@ def OMP_dispatch : Directive<"dispatch"> {
VersionedClause<OMPC_Novariants>,
VersionedClause<OMPC_Nocontext>
];
-}
-def OMP_masked : Directive<"masked"> {
- let allowedOnceClauses = [
- VersionedClause<OMPC_Filter>
- ];
+ let association = AS_Block;
}
def OMP_loop : Directive<"loop"> {
let allowedClauses = [
@@ -2083,6 +2207,7 @@ def OMP_loop : Directive<"loop"> {
VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_Order, 50>
];
+ let association = AS_Loop;
}
def OMP_teams_loop : Directive<"teams loop"> {
let allowedClauses = [
@@ -2102,6 +2227,7 @@ def OMP_teams_loop : Directive<"teams loop"> {
VersionedClause<OMPC_Order>,
VersionedClause<OMPC_ThreadLimit>,
];
+ let leafs = [OMP_Teams, OMP_loop];
}
def OMP_target_teams_loop : Directive<"target teams loop"> {
let allowedClauses = [
@@ -2131,6 +2257,7 @@ def OMP_target_teams_loop : Directive<"target teams loop"> {
VersionedClause<OMPC_ThreadLimit>,
VersionedClause<OMPC_OMPX_DynCGroupMem>,
];
+ let leafs = [OMP_Target, OMP_Teams, OMP_loop];
}
def OMP_parallel_loop : Directive<"parallel loop"> {
let allowedClauses = [
@@ -2152,6 +2279,7 @@ def OMP_parallel_loop : Directive<"parallel loop"> {
VersionedClause<OMPC_Order>,
VersionedClause<OMPC_ProcBind>,
];
+ let leafs = [OMP_Parallel, OMP_loop];
}
def OMP_target_parallel_loop : Directive<"target parallel loop"> {
let allowedClauses = [
@@ -2183,11 +2311,15 @@ def OMP_target_parallel_loop : Directive<"target parallel loop"> {
VersionedClause<OMPC_OMPX_DynCGroupMem>,
VersionedClause<OMPC_ThreadLimit, 51>,
];
+ let leafs = [OMP_Target, OMP_Parallel, OMP_loop];
}
def OMP_Metadirective : Directive<"metadirective"> {
let allowedClauses = [VersionedClause<OMPC_When>];
let allowedOnceClauses = [VersionedClause<OMPC_Default>];
+ let association = AS_None;
}
+
def OMP_Unknown : Directive<"unknown"> {
let isDefault = true;
+ let association = AS_None;
}
diff --git a/llvm/include/llvm/TableGen/DirectiveEmitter.h b/llvm/include/llvm/TableGen/DirectiveEmitter.h
index c86018715a48a1..208d3bac5b3dab 100644
--- a/llvm/include/llvm/TableGen/DirectiveEmitter.h
+++ b/llvm/include/llvm/TableGen/DirectiveEmitter.h
@@ -51,6 +51,10 @@ class DirectiveLanguage {
return Def->getValueAsBit("enableBitmaskEnumInNamespace");
}
+ std::vector<Record *> getAssociations() const {
+ return Records.getAllDerivedDefinitions("Association");
+ }
+
std::vector<Record *> getDirectives() const {
return Records.getAllDerivedDefinitions("Directive");
}
@@ -121,6 +125,14 @@ class Directive : public BaseRecord {
std::vector<Record *> getRequiredClauses() const {
return Def->getValueAsListOfDefs("requiredClauses");
}
+
+ std::vector<Record *> getLeafConstructs() const {
+ return Def->getValueAsListOfDefs("leafs");
+ }
+
+ Record *getAssociation() const {
+ return Def->getValueAsDef("association");
+ }
};
// Wrapper class that contains Clause's information defined in DirectiveBase.td
diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp
index 99eebacd6b3f32..0b078d936d81f8 100644
--- a/llvm/utils/TableGen/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/DirectiveEmitter.cpp
@@ -42,7 +42,8 @@ class IfDefScope {
// Generate enum class
static void GenerateEnumClass(const std::vector<Record *> &Records,
raw_ostream &OS, StringRef Enum, StringRef Prefix,
- const DirectiveLanguage &DirLang) {
+ const DirectiveLanguage &DirLang,
+ bool ExportEnums) {
OS << "\n";
OS << "enum class " << Enum << " {\n";
for (const auto &R : Records) {
@@ -59,7 +60,7 @@ static void GenerateEnumClass(const std::vector<Record *> &Records,
// At the same time we do not loose the strong type guarantees of the enum
// class, that is we cannot pass an unsigned as Directive without an explicit
// cast.
- if (DirLang.hasMakeEnumAvailableInNamespace()) {
+ if (ExportEnums) {
OS << "\n";
for (const auto &R : Records) {
BaseRecord Rec{R};
@@ -186,6 +187,7 @@ static void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) {
if (DirLang.hasEnableBitmaskEnumInNamespace())
OS << "\n#include \"llvm/ADT/BitmaskEnum.h\"\n";
+ OS << "#include \"llvm/ADT/SmallVector.h\"\n";
OS << "\n";
OS << "namespace llvm {\n";
@@ -200,13 +202,24 @@ static void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) {
if (DirLang.hasEnableBitmaskEnumInNamespace())
OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n";
+ // Emit Directive associations
+ std::vector<Record *> associations;
+ llvm::copy_if(
+ DirLang.getAssociations(), std::back_inserter(associations),
+ // Skip the "special" value
+ [](const Record *Def) { return Def->getName() != "AS_FromLeafs"; });
+ GenerateEnumClass(associations, OS, "Association",
+ /*Prefix=*/"", DirLang, /*ExportEnums=*/false);
+
// Emit Directive enumeration
GenerateEnumClass(DirLang.getDirectives(), OS, "Directive",
- DirLang.getDirectivePrefix(), DirLang);
+ DirLang.getDirectivePrefix(), DirLang,
+ DirLang.hasMakeEnumAvailableInNamespace());
// Emit Clause enumeration
GenerateEnumClass(DirLang.getClauses(), OS, "Clause",
- DirLang.getClausePrefix(), DirLang);
+ DirLang.getClausePrefix(), DirLang,
+ DirLang.hasMakeEnumAvailableInNamespace());
// Emit ClauseVal enumeration
std::string EnumHelperFuncs;
@@ -231,6 +244,8 @@ static void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) {
OS << "bool isAllowedClauseForDirective(Directive D, "
<< "Clause C, unsigned Version);\n";
OS << "\n";
+ OS << "const llvm::SmallVector<Directive> &getLeafConstructs(Directive D);\n";
+ OS << "Association getDirectiveAssociation(Directive D);\n";
if (EnumHelperFuncs.length() > 0) {
OS << EnumHelperFuncs;
OS << "\n";
@@ -435,6 +450,213 @@ static void GenerateIsAllowedClause(const DirectiveLanguage &DirLang,
OS << "}\n"; // End of function isAllowedClauseForDirective
}
+// Generate the getLeafConstructs function implementation.
+static void GenerateGetLeafConstructs(const DirectiveLanguage &DirLang,
+ raw_ostream &OS) {
+ auto getQualifiedName = [&](StringRef Formatted) -> std::string {
+ return (llvm::Twine("llvm::") + DirLang.getCppNamespace() +
+ "::Directive::" + DirLang.getDirectivePrefix() + Formatted)
+ .str();
+ };
+
+ // For each list of leafs, generate a static local object, then
+ // return a reference to that object for a given directive, e.g.
+ //
+ // static ListTy leafConstructs_A_B = { A, B };
+ // static ListTy leafConstructs_C_D_E = { C, D, E };
+ // switch (Dir) {
+ // case A_B:
+ // return leafConstructs_A_B;
+ // case C_D_E:
+ // return leafConstructs_C_D_E;
+ // }
+
+ // Map from a record that defines a directive to the name of the
+ // local object with the list of its leafs.
+ DenseMap<Record *, std::string> ListNames;
+
+ std::string DirectiveTypeName =
+ std::string("llvm::") + DirLang.getCppNamespace().str() + "::Directive";
+ std::string DirectiveListTypeName =
+ std::string("llvm::SmallVector<") + DirectiveTypeName + ">";
+
+ // const Container &llvm::<ns>::GetLeafConstructs(llvm::<ns>::Directive Dir)
+ OS << "const " << DirectiveListTypeName
+ << " &llvm::" << DirLang.getCppNamespace() << "::getLeafConstructs("
+ << DirectiveTypeName << " Dir) ";
+ OS << "{\n";
+
+ // Generate the locals.
+ for (Record *R : DirLang.getDirectives()) {
+ Directive Dir{R};
+
+ std::vector<Record *> LeafConstructs = Dir.getLeafConstructs();
+ if (LeafConstructs.empty())
+ continue;
+
+ std::string ListName = "leafConstructs_" + Dir.getFormattedName();
+ OS << " static " << DirectiveListTypeName << ' ' << ListName << " {\n";
+ for (Record *L : LeafConstructs) {
+ Directive LeafDir{L};
+ OS << " " << getQualifiedName(LeafDir.getFormattedName()) << ",\n";
+ }
+ OS << " };\n";
+ ListNames.insert(std::make_pair(R, std::move(ListName)));
+ }
+
+ OS << " static " << DirectiveListTypeName << " nothing {};\n";
+
+ OS << '\n';
+ OS << " switch (Dir) {\n";
+ for (Record *R : DirLang.getDirectives()) {
+ auto F = ListNames.find(R);
+ if (F == ListNames.end())
+ continue;
+
+ Directive Dir{R};
+ OS << " case " << getQualifiedName(Dir.getFormattedName()) << ":\n";
+ OS << " return " << F->second << ";\n";
+ }
+ OS << " default:\n";
+ OS << " return nothing;\n";
+ OS << " } // switch (Dir)\n";
+ OS << "}\n";
+}
+
+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,
+ Delimited,
+ Loop,
+ Separating,
+ FromLeafs,
+ Invalid,
+ };
+
+ std::vector<Record *> associations = DirLang.getAssociations();
+
+ auto getAssocValue = [](StringRef name) -> Association {
+ return StringSwitch<Association>(name)
+ .Case("AS_Block", Association::Block)
+ .Case("AS_Declaration", Association::Declaration)
+ .Case("AS_Delimited", Association::Delimited)
+ .Case("AS_Loop", Association::Loop)
+ .Case("AS_None", Association::None)
+ .Case("AS_Separating", Association::Separating)
+ .Case("AS_FromLeafs", Association::FromLeafs)
+ .Default(Association::Invalid);
+ };
+
+ auto getAssocName = [&](Association A) -> StringRef {
+ if (A != Association::Invalid && A != Association::FromLeafs) {
+ auto F = llvm::find_if(associations, [&](const Record *R) {
+ return getAssocValue(R->getName()) == A;
+ });
+ if (F != associations.end())
+ return (*F)->getValueAsString("name"); // enum name
+ }
+ llvm_unreachable("Unexpected association value");
+ };
+
+ auto errorPrefixFor = [&](Directive D) -> std::string {
+ return (Twine("Directive '") + D.getName() + "' in namespace '" +
+ DirLang.getCppNamespace() + "' ")
+ .str();
+ };
+
+ auto reduce = [&](Association A, Association B) -> Association {
+ if (A > B)
+ std::swap(A, B);
+
+ // Calculate the result using the following rules:
+ // x + x = x
+ // AS_None + x = x
+ // AS_Block + AS_Loop = AS_Loop
+ if (A == Association::None || A == B)
+ return B;
+ if (A == Association::Block && B == Association::Loop)
+ return B;
+ if (A == Association::Loop && B == Association::Block)
+ return A;
+ return Association::Invalid;
+ };
+
+ llvm::DenseMap<const Record *, Association> AsMap;
+
+ auto compAssocImpl = [&](const Record *R, auto &&Self) -> Association {
+ if (auto F = AsMap.find(R); F != AsMap.end())
+ return F->second;
+
+ Directive D{R};
+ Association AS = getAssocValue(D.getAssociation()->getName());
+ if (AS == Association::Invalid) {
+ PrintFatalError(errorPrefixFor(D) +
+ "has an unrecognized value for association: '" +
+ D.getAssociation()->getName() + "'");
+ }
+ if (AS != Association::FromLeafs) {
+ AsMap.insert(std::make_pair(R, AS));
+ return AS;
+ }
+ // Compute the association from leaf constructs.
+ std::vector<Record *> leafs = D.getLeafConstructs();
+ if (leafs.empty()) {
+ llvm::errs() << D.getName() << '\n';
+ PrintFatalError(errorPrefixFor(D) +
+ "requests association to be computed from leafs, "
+ "but it has no leafs");
+ }
+
+ Association Result = Self(leafs[0], Self);
+ for (int I = 1, E = leafs.size(); I < E; ++I) {
+ Association A = Self(leafs[I], Self);
+ Association R = reduce(Result, A);
+ if (R == Association::Invalid) {
+ PrintFatalError(errorPrefixFor(D) +
+ "has leafs with incompatible association values: " +
+ getAssocName(A) + " and " + getAssocName(R));
+ }
+ Result = R;
+ }
+
+ assert(Result != Association::Invalid);
+ assert(Result != Association::FromLeafs);
+ AsMap.insert(std::make_pair(R, Result));
+ return Result;
+ };
+
+ for (Record *R : DirLang.getDirectives())
+ compAssocImpl(R, compAssocImpl); // Updates AsMap.
+
+ auto getQualifiedName = [&](StringRef Formatted) -> std::string {
+ return (llvm::Twine("llvm::") + DirLang.getCppNamespace() +
+ "::Directive::" + DirLang.getDirectivePrefix() + Formatted)
+ .str();
+ };
+
+ std::string DirectiveTypeName =
+ std::string("llvm::") + DirLang.getCppNamespace().str() + "::Directive";
+ std::string AssociationTypeName =
+ std::string("llvm::") + DirLang.getCppNamespace().str() + "::Association";
+
+ OS << AssociationTypeName << " llvm::" << DirLang.getCppNamespace()
+ << "::getDirectiveAssociation(" << DirectiveTypeName << " Dir) {\n";
+ OS << " switch (Dir) {\n";
+ for (Record *R : DirLang.getDirectives()) {
+ if (auto F = AsMap.find(R); F != AsMap.end()) {
+ Directive Dir{R};
+ OS << " case " << getQualifiedName(Dir.getFormattedName()) << ":\n";
+ OS << " return " << AssociationTypeName
+ << "::" << getAssocName(F->second) << ";\n";
+ }
+ }
+ OS << " } // switch(Dir)\n";
+ OS << "}\n";
+}
+
// Generate a simple enum set with the give clauses.
static void GenerateClauseSet(const std::vector<Record *> &Clauses,
raw_ostream &OS, StringRef ClauseSetPrefix,
@@ -877,6 +1099,12 @@ void EmitDirectivesBasicImpl(const DirectiveLanguage &DirLang,
// isAllowedClauseForDirective(Directive D, Clause C, unsigned Version)
GenerateIsAllowedClause(DirLang, OS);
+
+ // getLeafConstructs(Directive D)
+ GenerateGetLeafConstructs(DirLang, OS);
+
+ // getDirectiveAssociation(Directive D)
+ GenerateGetDirectiveAssociation(DirLang, OS);
}
// Generate the implemenation section for the enumeration in the directive
More information about the cfe-commits
mailing list