-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[MLIR][OpenMP]Adding MLIR Op definition for scan #107925
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
Conversation
|
@llvm/pr-subscribers-mlir-openmp @llvm/pr-subscribers-mlir Author: Anchu Rajendran S (anchuraj) ChangesMLIR Op representation of scan operation. Scan directive helps to specify scan computations. Full diff: https://github.com/llvm/llvm-project/pull/107925.diff 5 Files Affected:
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
index 38e4d8f245e4fa..af96f24c8fe2c2 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h
@@ -105,6 +105,13 @@ struct IfClauseOps {
Value ifVar;
};
+struct InclusiveClauseOps {
+ llvm::SmallVector<Value> inclusiveVars;
+};
+
+struct ExclusiveClauseOps {
+ llvm::SmallVector<Value> exclusiveVars;
+};
struct InReductionClauseOps {
llvm::SmallVector<Value> inReductionVars;
llvm::SmallVector<bool> inReductionByref;
@@ -261,6 +268,8 @@ using LoopNestOperands = detail::Clauses<LoopRelatedOps>;
using MaskedOperands = detail::Clauses<FilterClauseOps>;
+using ScanOperands = detail::Clauses<InclusiveClauseOps, ExclusiveClauseOps>;
+
using OrderedOperands = detail::Clauses<DoacrossClauseOps>;
using OrderedRegionOperands = detail::Clauses<ParallelizationLevelClauseOps>;
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index e703c323edbc8a..79b54545ef5331 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -503,6 +503,61 @@ class OpenMP_IsDevicePtrClauseSkip<
def OpenMP_IsDevicePtrClause : OpenMP_IsDevicePtrClauseSkip<>;
+//===----------------------------------------------------------------------===//
+// V5.2: [5.4.7] `inclusive` clause
+//===----------------------------------------------------------------------===//
+
+class OpenMP_InclusiveClauseSkip<
+ bit traits = false, bit arguments = false, bit assemblyFormat = false,
+ bit description = false, bit extraClassDeclaration = false
+ > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
+ description, extraClassDeclaration> {
+ let arguments = (ins
+ Variadic<AnyType>:$inclusive_vars
+ );
+
+ let assemblyFormat = [{
+ `inclusive` `(` $inclusive_vars `:` type($inclusive_vars) `)`
+ }];
+
+ let description = [{
+ The inclusive clause is used on a separating directive that separates a
+ structured block into two structured block sequences. If the inclusive
+ clause is specified, the input phase includes the preceding structured block
+ sequence and the scan phase includes the following structured block sequence.
+ }];
+}
+
+def OpenMP_InclusiveClause : OpenMP_InclusiveClauseSkip<>;
+
+//===----------------------------------------------------------------------===//
+// V5.2: [5.4.7] `exclusive` clause
+//===----------------------------------------------------------------------===//
+
+class OpenMP_ExclusiveClauseSkip<
+ bit traits = false, bit arguments = false, bit assemblyFormat = false,
+ bit description = false, bit extraClassDeclaration = false
+ > : OpenMP_Clause</*isRequired=*/false, traits, arguments, assemblyFormat,
+ description, extraClassDeclaration> {
+ let arguments = (ins
+ Variadic<AnyType>:$exclusive_vars
+ );
+
+ let assemblyFormat = [{
+ `exclusive` `(` $exclusive_vars `:` type($exclusive_vars) `)`
+ }];
+
+ let description = [{
+ The exclusive clause is used on a separating directive that separates a
+ structured block into two structured block sequences. If the exclusive clause
+ is specified, the input phase excludes the preceding structured block
+ sequence and instead includes the following structured block sequence,
+ while the scan phase includes the preceding structured block sequence.
+ }];
+}
+
+def OpenMP_ExclusiveClause : OpenMP_ExclusiveClauseSkip<>;
+
//===----------------------------------------------------------------------===//
// V5.2: [5.4.6] `linear` clause
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 1aa4e771cd4dea..2a81ac2f09072d 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -1202,6 +1202,20 @@ def OrderedRegionOp : OpenMP_Op<"ordered.region", clauses = [
let hasVerifier = 1;
}
+def ScanOp : OpenMP_Op<"scan", traits = [
+ AttrSizedOperandSegments
+ ], clauses = [OpenMP_InclusiveClause, OpenMP_ExclusiveClause]> {
+ let summary = "scan construct with the region";
+ let description = [{
+ The scan without region is a stand-alone directive that
+ }] # clausesDescription;
+
+ let builders = [
+ OpBuilder<(ins CArg<"const ScanOperands &">:$clauses)>
+ ];
+
+}
+
//===----------------------------------------------------------------------===//
// 2.17.5 taskwait Construct
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 1a9b87f0d68c9d..04b4f9b8e8b254 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2619,6 +2619,15 @@ LogicalResult PrivateClauseOp::verify() {
return success();
}
+//===----------------------------------------------------------------------===//
+// Spec 5.2: Scan construct (5.6)
+//===----------------------------------------------------------------------===//
+
+void ScanOp::build(OpBuilder &builder, OperationState &state,
+ const ScanOperands &clauses) {
+ ScanOp::build(builder, state, clauses.inclusiveVars, clauses.exclusiveVars);
+}
+
//===----------------------------------------------------------------------===//
// Spec 5.2: Masked construct (10.5)
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index dce5b3950def49..09db285a0274ee 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -30,6 +30,14 @@ func.func @omp_masked(%filtered_thread_id : i32) -> () {
return
}
+func.func @omp_scan(%arg0 : memref<i32>) -> () {
+ // CHECK: omp.scan inclusive(%{{.*}} : memref<i32>)
+ omp.scan inclusive(%arg0 : memref<i32>)
+ // CHECK: omp.scan exclusive(%{{.*}} : memref<i32>)
+ omp.scan exclusive(%arg0 : memref<i32>)
+ return
+}
+
func.func @omp_taskwait() -> () {
// CHECK: omp.taskwait
omp.taskwait
|
skatrak
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you Anchu for this work. I have some nits, but this generally looks good. However, I think that the new operation would need a verifier.
A good start could be to check that values in a scan directive appear on a parent reduction with an inscan modifier and that there is a single omp.scan applied to that construct, but inscan is not currently supported. Maybe the check could be to check that values passed to inclusive and exclusive are block arguments attached to a reduction and that the operation defining that reduction only holds a single omp.scan, adding a TODO comment to check the inscan modifier when supported. Then, update the test in ops.mlir and add a couple to invalid.mlir to exercise these verifier checks. Let me know what you think about this.
When rebasing, notice you no longer need to add definitions to OpenMPClauseOperands.h. Also, the new clauses don't have to pass an isRequired template argument to OpenMP_Clause (instead, rename assemblyFormat to {req,opt}AssemblyFormat as needed).
| // V5.2: [5.4.7] `inclusive` clause | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| class OpenMP_InclusiveClauseSkip< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Move definitions for these new clauses to keep alphabetical sorting in the file.
|
|
||
| let description = [{ | ||
| The inclusive clause is used on a separating directive that separates a | ||
| structured block into two structured block sequences. If the inclusive |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| structured block into two structured block sequences. If the inclusive | |
| structured block into two structured block sequences. If it |
|
|
||
| let description = [{ | ||
| The exclusive clause is used on a separating directive that separates a | ||
| structured block into two structured block sequences. If the exclusive clause |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| structured block into two structured block sequences. If the exclusive clause | |
| structured block into two structured block sequences. If it |
| let builders = [ | ||
| OpBuilder<(ins CArg<"const ScanOperands &">:$clauses)> | ||
| ]; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| def ScanOp : OpenMP_Op<"scan", traits = [ | ||
| AttrSizedOperandSegments | ||
| ], clauses = [OpenMP_InclusiveClause, OpenMP_ExclusiveClause]> { | ||
| let summary = "scan construct with the region"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be "scan directive"?
| ], clauses = [OpenMP_InclusiveClause, OpenMP_ExclusiveClause]> { | ||
| let summary = "scan construct with the region"; | ||
| let description = [{ | ||
| The scan without region is a stand-alone directive that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the description is not complete.
|
Will open a new PR addressing these suggestions and adding the complete changes for supporting scan. |
MLIR Op representation of scan operation. Scan directive helps to specify scan computations.
Related PR: Parsing and Semantic changes for scan