Skip to content

Commit d534a63

Browse files
committed
[OpenMP] Add workdistribute construct in openMP dialect and in llvm frontend.
1 parent a5f1ddd commit d534a63

File tree

5 files changed

+205
-0
lines changed

5 files changed

+205
-0
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,17 @@ def OMP_EndWorkshare : Directive<[Spelling<"end workshare">]> {
13221322
let category = OMP_Workshare.category;
13231323
let languages = [L_Fortran];
13241324
}
1325+
def OMP_Workdistribute : Directive<[Spelling<"workdistribute">]> {
1326+
let association = AS_Block;
1327+
let category = CA_Executable;
1328+
let languages = [L_Fortran];
1329+
}
1330+
def OMP_EndWorkdistribute : Directive<[Spelling<"end workdistribute">]> {
1331+
let leafConstructs = OMP_Workdistribute.leafConstructs;
1332+
let association = OMP_Workdistribute.association;
1333+
let category = OMP_Workdistribute.category;
1334+
let languages = [L_Fortran];
1335+
}
13251336

13261337
//===----------------------------------------------------------------------===//
13271338
// Definitions of OpenMP compound directives

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

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

2212+
//===----------------------------------------------------------------------===//
2213+
// workdistribute Construct
2214+
//===----------------------------------------------------------------------===//
2215+
2216+
def WorkdistributeOp : OpenMP_Op<"workdistribute"> {
2217+
let summary = "workdistribute directive";
2218+
let description = [{
2219+
workdistribute divides execution of the enclosed structured block into
2220+
separate units of work, each executed only once by each
2221+
initial thread in the league.
2222+
```
2223+
!$omp target teams
2224+
!$omp workdistribute
2225+
y = a * x + y
2226+
!$omp end workdistribute
2227+
!$omp end target teams
2228+
```
2229+
}];
2230+
let regions = (region AnyRegion:$region);
2231+
let hasVerifier = 1;
2232+
let assemblyFormat = "$region attr-dict";
2233+
}
2234+
22122235
#endif // OPENMP_OPS

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

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

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

mlir/test/Dialect/OpenMP/invalid.mlir

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3017,3 +3017,110 @@ func.func @invalid_allocate_allocator(%arg0 : memref<i32>) -> () {
30173017

30183018
return
30193019
}
3020+
3021+
// -----
3022+
func.func @invalid_workdistribute_empty_region() -> () {
3023+
omp.teams {
3024+
// expected-error @below {{region cannot be empty}}
3025+
omp.workdistribute {
3026+
}
3027+
omp.terminator
3028+
}
3029+
return
3030+
}
3031+
3032+
// -----
3033+
func.func @invalid_workdistribute_no_terminator() -> () {
3034+
omp.teams {
3035+
// expected-error @below {{region must be terminated with omp.terminator}}
3036+
omp.workdistribute {
3037+
%c0 = arith.constant 0 : i32
3038+
}
3039+
omp.terminator
3040+
}
3041+
return
3042+
}
3043+
3044+
// -----
3045+
func.func @invalid_workdistribute_wrong_terminator() -> () {
3046+
omp.teams {
3047+
// expected-error @below {{region must be terminated with omp.terminator}}
3048+
omp.workdistribute {
3049+
%c0 = arith.constant 0 : i32
3050+
func.return
3051+
}
3052+
omp.terminator
3053+
}
3054+
return
3055+
}
3056+
3057+
// -----
3058+
func.func @invalid_workdistribute_multiple_terminators() -> () {
3059+
omp.teams {
3060+
// expected-error @below {{region must have exactly one terminator}}
3061+
omp.workdistribute {
3062+
%cond = arith.constant true
3063+
cf.cond_br %cond, ^bb1, ^bb2
3064+
^bb1:
3065+
omp.terminator
3066+
^bb2:
3067+
omp.terminator
3068+
}
3069+
omp.terminator
3070+
}
3071+
return
3072+
}
3073+
3074+
// -----
3075+
func.func @invalid_workdistribute_with_barrier() -> () {
3076+
omp.teams {
3077+
// expected-error @below {{explicit barriers are not allowed in workdistribute region}}
3078+
omp.workdistribute {
3079+
%c0 = arith.constant 0 : i32
3080+
omp.barrier
3081+
omp.terminator
3082+
}
3083+
omp.terminator
3084+
}
3085+
return
3086+
}
3087+
3088+
// -----
3089+
func.func @invalid_workdistribute_nested_parallel() -> () {
3090+
omp.teams {
3091+
// expected-error @below {{nested parallel constructs not allowed in workdistribute}}
3092+
omp.workdistribute {
3093+
omp.parallel {
3094+
omp.terminator
3095+
}
3096+
omp.terminator
3097+
}
3098+
omp.terminator
3099+
}
3100+
return
3101+
}
3102+
3103+
// -----
3104+
// Test: nested teams not allowed in workdistribute
3105+
func.func @invalid_workdistribute_nested_teams() -> () {
3106+
omp.teams {
3107+
// expected-error @below {{nested teams constructs not allowed in workdistribute}}
3108+
omp.workdistribute {
3109+
omp.teams {
3110+
omp.terminator
3111+
}
3112+
omp.terminator
3113+
}
3114+
omp.terminator
3115+
}
3116+
return
3117+
}
3118+
3119+
// -----
3120+
func.func @invalid_workdistribute() -> () {
3121+
// expected-error @below {{workdistribute must be nested under teams}}
3122+
omp.workdistribute {
3123+
omp.terminator
3124+
}
3125+
return
3126+
}

mlir/test/Dialect/OpenMP/ops.mlir

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3238,3 +3238,15 @@ func.func @omp_allocate_dir(%arg0 : memref<i32>, %arg1 : memref<i32>) -> () {
32383238
return
32393239
}
32403240

3241+
// CHECK-LABEL: func.func @omp_workdistribute
3242+
func.func @omp_workdistribute() {
3243+
// CHECK: omp.teams
3244+
omp.teams {
3245+
// CHECK: omp.workdistribute
3246+
omp.workdistribute {
3247+
omp.terminator
3248+
}
3249+
omp.terminator
3250+
}
3251+
return
3252+
}

0 commit comments

Comments
 (0)