Skip to content

Commit b74fde8

Browse files
committed
Add workdistribute construct in openMP dialect and in llvm frontend (llvm#154376)
This PR adds workdistribute mlir op in omp dialect and also in llvm frontend. The work in this PR is c-p and updated from @ivanradanov commits from coexecute implementation: flang_workdistribute_iwomp_2024
1 parent f007977 commit b74fde8

File tree

5 files changed

+254
-0
lines changed

5 files changed

+254
-0
lines changed

llvm/include/llvm/Frontend/OpenMP/OMP.td

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,17 @@ def OMP_EndWorkshare : Directive<[Spelling<"end workshare">]> {
13091309
let category = OMP_Workshare.category;
13101310
let languages = [L_Fortran];
13111311
}
1312+
def OMP_Workdistribute : Directive<[Spelling<"workdistribute">]> {
1313+
let association = AS_Block;
1314+
let category = CA_Executable;
1315+
let languages = [L_Fortran];
1316+
}
1317+
def OMP_EndWorkdistribute : Directive<[Spelling<"end workdistribute">]> {
1318+
let leafConstructs = OMP_Workdistribute.leafConstructs;
1319+
let association = OMP_Workdistribute.association;
1320+
let category = OMP_Workdistribute.category;
1321+
let languages = [L_Fortran];
1322+
}
13121323

13131324
//===----------------------------------------------------------------------===//
13141325
// Definitions of OpenMP compound directives
@@ -2452,6 +2463,35 @@ def OMP_TargetTeamsDistributeSimd
24522463
let leafConstructs = [OMP_Target, OMP_Teams, OMP_Distribute, OMP_Simd];
24532464
let category = CA_Executable;
24542465
}
2466+
def OMP_TargetTeamsWorkdistribute : Directive<[Spelling<"target teams workdistribute">]> {
2467+
let allowedClauses = [
2468+
VersionedClause<OMPC_Allocate>,
2469+
VersionedClause<OMPC_Depend>,
2470+
VersionedClause<OMPC_FirstPrivate>,
2471+
VersionedClause<OMPC_HasDeviceAddr, 51>,
2472+
VersionedClause<OMPC_If>,
2473+
VersionedClause<OMPC_IsDevicePtr>,
2474+
VersionedClause<OMPC_Map>,
2475+
VersionedClause<OMPC_OMPX_Attribute>,
2476+
VersionedClause<OMPC_Private>,
2477+
VersionedClause<OMPC_Reduction>,
2478+
VersionedClause<OMPC_Shared>,
2479+
VersionedClause<OMPC_UsesAllocators, 50>,
2480+
];
2481+
let allowedOnceClauses = [
2482+
VersionedClause<OMPC_Default>,
2483+
VersionedClause<OMPC_DefaultMap>,
2484+
VersionedClause<OMPC_Device>,
2485+
VersionedClause<OMPC_NoWait>,
2486+
VersionedClause<OMPC_NumTeams>,
2487+
VersionedClause<OMPC_OMPX_DynCGroupMem>,
2488+
VersionedClause<OMPC_OMPX_Bare>,
2489+
VersionedClause<OMPC_ThreadLimit>,
2490+
];
2491+
let leafConstructs = [OMP_Target, OMP_Teams, OMP_Workdistribute];
2492+
let category = CA_Executable;
2493+
let languages = [L_Fortran];
2494+
}
24552495
def OMP_target_teams_loop : Directive<[Spelling<"target teams loop">]> {
24562496
let allowedClauses = [
24572497
VersionedClause<OMPC_Allocate>,
@@ -2682,6 +2722,25 @@ def OMP_TeamsDistributeSimd : Directive<[Spelling<"teams distribute simd">]> {
26822722
let leafConstructs = [OMP_Teams, OMP_Distribute, OMP_Simd];
26832723
let category = CA_Executable;
26842724
}
2725+
def OMP_TeamsWorkdistribute : Directive<[Spelling<"teams workdistribute">]> {
2726+
let allowedClauses = [
2727+
VersionedClause<OMPC_Allocate>,
2728+
VersionedClause<OMPC_FirstPrivate>,
2729+
VersionedClause<OMPC_OMPX_Attribute>,
2730+
VersionedClause<OMPC_Private>,
2731+
VersionedClause<OMPC_Reduction>,
2732+
VersionedClause<OMPC_Shared>,
2733+
];
2734+
let allowedOnceClauses = [
2735+
VersionedClause<OMPC_Default>,
2736+
VersionedClause<OMPC_If, 52>,
2737+
VersionedClause<OMPC_NumTeams>,
2738+
VersionedClause<OMPC_ThreadLimit>,
2739+
];
2740+
let leafConstructs = [OMP_Teams, OMP_Workdistribute];
2741+
let category = CA_Executable;
2742+
let languages = [L_Fortran];
2743+
}
26852744
def OMP_teams_loop : Directive<[Spelling<"teams loop">]> {
26862745
let allowedClauses = [
26872746
VersionedClause<OMPC_Allocate>,

mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2184,4 +2184,27 @@ def TargetFreeMemOp : OpenMP_Op<"target_freemem",
21842184
let assemblyFormat = "$device `,` $heapref attr-dict `:` type($device) `,` qualified(type($heapref))";
21852185
}
21862186

2187+
//===----------------------------------------------------------------------===//
2188+
// workdistribute Construct
2189+
//===----------------------------------------------------------------------===//
2190+
2191+
def WorkdistributeOp : OpenMP_Op<"workdistribute"> {
2192+
let summary = "workdistribute directive";
2193+
let description = [{
2194+
workdistribute divides execution of the enclosed structured block into
2195+
separate units of work, each executed only once by each
2196+
initial thread in the league.
2197+
```
2198+
!$omp target teams
2199+
!$omp workdistribute
2200+
y = a * x + y
2201+
!$omp end workdistribute
2202+
!$omp end target teams
2203+
```
2204+
}];
2205+
let regions = (region AnyRegion:$region);
2206+
let hasVerifier = 1;
2207+
let assemblyFormat = "$region attr-dict";
2208+
}
2209+
21872210
#endif // OPENMP_OPS

mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3967,6 +3967,58 @@ llvm::LogicalResult omp::TargetAllocMemOp::verify() {
39673967
return mlir::success();
39683968
}
39693969

3970+
//===----------------------------------------------------------------------===//
3971+
// WorkdistributeOp
3972+
//===----------------------------------------------------------------------===//
3973+
3974+
LogicalResult WorkdistributeOp::verify() {
3975+
// Check that region exists and is not empty
3976+
Region &region = getRegion();
3977+
if (region.empty())
3978+
return emitOpError("region cannot be empty");
3979+
// Verify single entry point.
3980+
Block &entryBlock = region.front();
3981+
if (entryBlock.empty())
3982+
return emitOpError("region must contain a structured block");
3983+
// Verify single exit point.
3984+
bool hasTerminator = false;
3985+
for (Block &block : region) {
3986+
if (isa<TerminatorOp>(block.back())) {
3987+
if (hasTerminator) {
3988+
return emitOpError("region must have exactly one terminator");
3989+
}
3990+
hasTerminator = true;
3991+
}
3992+
}
3993+
if (!hasTerminator) {
3994+
return emitOpError("region must be terminated with omp.terminator");
3995+
}
3996+
auto walkResult = region.walk([&](Operation *op) -> WalkResult {
3997+
// No implicit barrier at end
3998+
if (isa<BarrierOp>(op)) {
3999+
return emitOpError(
4000+
"explicit barriers are not allowed in workdistribute region");
4001+
}
4002+
// Check for invalid nested constructs
4003+
if (isa<ParallelOp>(op)) {
4004+
return emitOpError(
4005+
"nested parallel constructs not allowed in workdistribute");
4006+
}
4007+
if (isa<TeamsOp>(op)) {
4008+
return emitOpError(
4009+
"nested teams constructs not allowed in workdistribute");
4010+
}
4011+
return WalkResult::advance();
4012+
});
4013+
if (walkResult.wasInterrupted())
4014+
return failure();
4015+
4016+
Operation *parentOp = (*this)->getParentOp();
4017+
if (!llvm::dyn_cast<TeamsOp>(parentOp))
4018+
return emitOpError("workdistribute must be nested under teams");
4019+
return success();
4020+
}
4021+
39704022
#define GET_ATTRDEF_CLASSES
39714023
#include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
39724024

mlir/test/Dialect/OpenMP/invalid.mlir

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2987,3 +2987,110 @@ llvm.func @invalid_mapper(%0 : !llvm.ptr) {
29872987
}
29882988
llvm.return
29892989
}
2990+
2991+
// -----
2992+
func.func @invalid_workdistribute_empty_region() -> () {
2993+
omp.teams {
2994+
// expected-error @below {{region cannot be empty}}
2995+
omp.workdistribute {
2996+
}
2997+
omp.terminator
2998+
}
2999+
return
3000+
}
3001+
3002+
// -----
3003+
func.func @invalid_workdistribute_no_terminator() -> () {
3004+
omp.teams {
3005+
// expected-error @below {{region must be terminated with omp.terminator}}
3006+
omp.workdistribute {
3007+
%c0 = arith.constant 0 : i32
3008+
}
3009+
omp.terminator
3010+
}
3011+
return
3012+
}
3013+
3014+
// -----
3015+
func.func @invalid_workdistribute_wrong_terminator() -> () {
3016+
omp.teams {
3017+
// expected-error @below {{region must be terminated with omp.terminator}}
3018+
omp.workdistribute {
3019+
%c0 = arith.constant 0 : i32
3020+
func.return
3021+
}
3022+
omp.terminator
3023+
}
3024+
return
3025+
}
3026+
3027+
// -----
3028+
func.func @invalid_workdistribute_multiple_terminators() -> () {
3029+
omp.teams {
3030+
// expected-error @below {{region must have exactly one terminator}}
3031+
omp.workdistribute {
3032+
%cond = arith.constant true
3033+
cf.cond_br %cond, ^bb1, ^bb2
3034+
^bb1:
3035+
omp.terminator
3036+
^bb2:
3037+
omp.terminator
3038+
}
3039+
omp.terminator
3040+
}
3041+
return
3042+
}
3043+
3044+
// -----
3045+
func.func @invalid_workdistribute_with_barrier() -> () {
3046+
omp.teams {
3047+
// expected-error @below {{explicit barriers are not allowed in workdistribute region}}
3048+
omp.workdistribute {
3049+
%c0 = arith.constant 0 : i32
3050+
omp.barrier
3051+
omp.terminator
3052+
}
3053+
omp.terminator
3054+
}
3055+
return
3056+
}
3057+
3058+
// -----
3059+
func.func @invalid_workdistribute_nested_parallel() -> () {
3060+
omp.teams {
3061+
// expected-error @below {{nested parallel constructs not allowed in workdistribute}}
3062+
omp.workdistribute {
3063+
omp.parallel {
3064+
omp.terminator
3065+
}
3066+
omp.terminator
3067+
}
3068+
omp.terminator
3069+
}
3070+
return
3071+
}
3072+
3073+
// -----
3074+
// Test: nested teams not allowed in workdistribute
3075+
func.func @invalid_workdistribute_nested_teams() -> () {
3076+
omp.teams {
3077+
// expected-error @below {{nested teams constructs not allowed in workdistribute}}
3078+
omp.workdistribute {
3079+
omp.teams {
3080+
omp.terminator
3081+
}
3082+
omp.terminator
3083+
}
3084+
omp.terminator
3085+
}
3086+
return
3087+
}
3088+
3089+
// -----
3090+
func.func @invalid_workdistribute() -> () {
3091+
// expected-error @below {{workdistribute must be nested under teams}}
3092+
omp.workdistribute {
3093+
omp.terminator
3094+
}
3095+
return
3096+
}

mlir/test/Dialect/OpenMP/ops.mlir

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3197,3 +3197,16 @@ func.func @omp_workshare_loop_wrapper_attrs(%idx : index) {
31973197
}
31983198
return
31993199
}
3200+
3201+
// CHECK-LABEL: func.func @omp_workdistribute
3202+
func.func @omp_workdistribute() {
3203+
// CHECK: omp.teams
3204+
omp.teams {
3205+
// CHECK: omp.workdistribute
3206+
omp.workdistribute {
3207+
omp.terminator
3208+
}
3209+
omp.terminator
3210+
}
3211+
return
3212+
}

0 commit comments

Comments
 (0)