Skip to content

[Frontend] Add leaf constructs and association to OpenMP/ACC directives #83625

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Mar 6, 2024
Merged
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;
}
Loading