Skip to content

Commit

Permalink
[Frontend] Add leaf constructs and association to OpenMP/ACC directiv…
Browse files Browse the repository at this point in the history
…es (#83625)

Add members "leafConstructs" and "association" to .td describing
OpenMP/ACC directives. The naming follows the terminology used in the
OpenMP standard: a "leaf" construct is a construct that is itself not a
composition or a combination of other 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.
  • Loading branch information
kparzysz committed Mar 6, 2024
1 parent 571d5af commit 67c82d6
Show file tree
Hide file tree
Showing 8 changed files with 562 additions and 123 deletions.
129 changes: 33 additions & 96 deletions clang/lib/Basic/OpenMPKinds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -619,44 +595,20 @@ 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_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) {
Expand All @@ -665,60 +617,45 @@ 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;
ArrayRef<Directive> Leaves = getLeafConstructs(DKind);
return !Leaves.empty() && Leaves.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 (getDirectiveAssociation(DKind) != Association::Loop)
return false;
// Formally, OMPD_end_do_simd also has a loop association, but
// it's a Fortran-specific directive.

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;
ArrayRef<Directive> Leaves = getLeafConstructs(Kind);
return !Leaves.empty() && Leaves.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;
ArrayRef<Directive> Leaves = getLeafConstructs(Kind);
return !Leaves.empty() && Leaves.back() == OMPD_loop;
}

bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
Expand Down
36 changes: 36 additions & 0 deletions llvm/include/llvm/Frontend/Directive/DirectiveBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -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_FromLeaves 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_FromLeaves : Association<"FromLeaves"> {} // See below
// AS_FromLeaves 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_FromLeaves" 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.
Expand All @@ -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> leafConstructs = [];

// Set directive used by default when unknown.
bit isDefault = false;

// What the directive is associated with.
Association association = AS_FromLeaves;
}
27 changes: 25 additions & 2 deletions llvm/include/llvm/Frontend/OpenACC/ACC.td
Original file line number Diff line number Diff line change
Expand Up @@ -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"> {
Expand All @@ -290,6 +292,7 @@ def ACC_Data : Directive<"data"> {
VersionedClause<ACCC_NoCreate>,
VersionedClause<ACCC_Present>
];
let association = AS_Block;
}

// 2.13
Expand All @@ -304,6 +307,7 @@ def ACC_Declare : Directive<"declare"> {
VersionedClause<ACCC_DeviceResident>,
VersionedClause<ACCC_Link>
];
let association = AS_None;
}

// 2.5.3
Expand All @@ -329,6 +333,7 @@ def ACC_Kernels : Directive<"kernels"> {
VersionedClause<ACCC_Self>,
VersionedClause<ACCC_VectorLength>
];
let association = AS_Block;
}

// 2.5.1
Expand Down Expand Up @@ -357,6 +362,7 @@ def ACC_Parallel : Directive<"parallel"> {
VersionedClause<ACCC_If>,
VersionedClause<ACCC_Self>
];
let association = AS_Block;
}

// 2.5.2
Expand Down Expand Up @@ -384,6 +390,7 @@ def ACC_Serial : Directive<"serial"> {
VersionedClause<ACCC_If>,
VersionedClause<ACCC_Self>
];
let association = AS_Block;
}

// 2.9
Expand All @@ -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"> {
Expand All @@ -415,6 +425,7 @@ def ACC_Init : Directive<"init"> {
VersionedClause<ACCC_DeviceType>,
VersionedClause<ACCC_If>
];
let association = AS_None;
}

// 2.15.1
Expand All @@ -430,6 +441,7 @@ def ACC_Routine : Directive<"routine"> {
let allowedOnceClauses = [
VersionedClause<ACCC_NoHost>
];
let association = AS_Declaration;
}

// 2.14.3
Expand All @@ -448,6 +460,7 @@ def ACC_Set : Directive<"set"> {
VersionedClause<ACCC_DeviceNum>,
VersionedClause<ACCC_DeviceType>
];
let association = AS_None;
}

// 2.14.2
Expand All @@ -457,6 +470,7 @@ def ACC_Shutdown : Directive<"shutdown"> {
VersionedClause<ACCC_DeviceType>,
VersionedClause<ACCC_If>
];
let association = AS_None;
}

// 2.14.4
Expand All @@ -475,6 +489,7 @@ def ACC_Update : Directive<"update"> {
VersionedClause<ACCC_Host>,
VersionedClause<ACCC_Self>
];
let association = AS_None;
}

// 2.16.3
Expand All @@ -483,6 +498,7 @@ def ACC_Wait : Directive<"wait"> {
VersionedClause<ACCC_Async>,
VersionedClause<ACCC_If>
];
let association = AS_None;
}

// 2.14.6
Expand All @@ -499,6 +515,7 @@ def ACC_EnterData : Directive<"enter data"> {
VersionedClause<ACCC_Create>,
VersionedClause<ACCC_Copyin>
];
let association = AS_None;
}

// 2.14.7
Expand All @@ -516,6 +533,7 @@ def ACC_ExitData : Directive<"exit data"> {
VersionedClause<ACCC_Delete>,
VersionedClause<ACCC_Detach>
];
let association = AS_None;
}

// 2.8
Expand All @@ -527,6 +545,7 @@ def ACC_HostData : Directive<"host_data"> {
let requiredClauses = [
VersionedClause<ACCC_UseDevice>
];
let association = AS_Block;
}

// 2.11
Expand Down Expand Up @@ -564,6 +583,7 @@ def ACC_KernelsLoop : Directive<"kernels loop"> {
VersionedClause<ACCC_Independent>,
VersionedClause<ACCC_Seq>
];
let leafConstructs = [ACC_Kernels, ACC_Loop];
}

// 2.11
Expand Down Expand Up @@ -602,6 +622,7 @@ def ACC_ParallelLoop : Directive<"parallel loop"> {
VersionedClause<ACCC_Independent>,
VersionedClause<ACCC_Seq>
];
let leafConstructs = [ACC_Parallel, ACC_Loop];
}

// 2.11
Expand Down Expand Up @@ -637,8 +658,10 @@ def ACC_SerialLoop : Directive<"serial loop"> {
VersionedClause<ACCC_Independent>,
VersionedClause<ACCC_Seq>
];
let leafConstructs = [ACC_Serial, ACC_Loop];
}

def ACC_Unknown : Directive<"unknown"> {
let isDefault = true;
let association = AS_None;
}

0 comments on commit 67c82d6

Please sign in to comment.