aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKareem Ergawy <kareem.ergawy@amd.com>2024-11-08 10:37:57 +0100
committerGitHub <noreply@github.com>2024-11-08 10:37:57 +0100
commitd74127e78aa7f8ab07b0926d25920444dde6c73c (patch)
tree22a5817bb92ec9f2de1c23cae9c668a9e492e82b
parent4f3bf1c62ceb85d2e33857ada26b565822e65600 (diff)
downloadllvm-d74127e78aa7f8ab07b0926d25920444dde6c73c.zip
llvm-d74127e78aa7f8ab07b0926d25920444dde6c73c.tar.gz
llvm-d74127e78aa7f8ab07b0926d25920444dde6c73c.tar.bz2
[flang][OpenMP][MLIR] Add MLIR op for loop directive (#113911)
Adds MLIR op that corresponds to the `loop` directive.
-rw-r--r--llvm/include/llvm/Frontend/OpenMP/OMP.td11
-rw-r--r--mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td25
-rw-r--r--mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td44
-rw-r--r--mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp17
-rw-r--r--mlir/test/Dialect/OpenMP/invalid.mlir46
-rw-r--r--mlir/test/Dialect/OpenMP/ops.mlir40
6 files changed, 183 insertions, 0 deletions
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 0fc0f06..d1cc753b 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -71,10 +71,21 @@ def OMPC_AtomicDefaultMemOrder : Clause<"atomic_default_mem_order"> {
let clangClass = "OMPAtomicDefaultMemOrderClause";
let flangClass = "OmpAtomicDefaultMemOrderClause";
}
+
+def OMP_BIND_parallel : ClauseVal<"parallel",1,1> {}
+def OMP_BIND_teams : ClauseVal<"teams",2,1> {}
+def OMP_BIND_thread : ClauseVal<"thread",3,1> { let isDefault = true; }
def OMPC_Bind : Clause<"bind"> {
let clangClass = "OMPBindClause";
let flangClass = "OmpBindClause";
+ let enumClauseValue = "BindKind";
+ let allowedClauseValues = [
+ OMP_BIND_parallel,
+ OMP_BIND_teams,
+ OMP_BIND_thread
+ ];
}
+
def OMP_CANCELLATION_CONSTRUCT_Parallel : ClauseVal<"parallel", 1, 1> {}
def OMP_CANCELLATION_CONSTRUCT_Loop : ClauseVal<"loop", 2, 1> {}
def OMP_CANCELLATION_CONSTRUCT_Sections : ClauseVal<"sections", 3, 1> {}
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index 886554f..855deab 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -108,6 +108,31 @@ class OpenMP_CancelDirectiveNameClauseSkip<
def OpenMP_CancelDirectiveNameClause : OpenMP_CancelDirectiveNameClauseSkip<>;
//===----------------------------------------------------------------------===//
+// V5.2: [11.7.1] `bind` clause
+//===----------------------------------------------------------------------===//
+
+class OpenMP_BindClauseSkip<
+ bit traits = false, bit arguments = false, bit assemblyFormat = false,
+ bit description = false, bit extraClassDeclaration = false
+ > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+ extraClassDeclaration> {
+ let arguments = (ins
+ OptionalAttr<BindKindAttr>:$bind_kind
+ );
+
+ let optAssemblyFormat = [{
+ `bind` `(` custom<ClauseAttr>($bind_kind) `)`
+ }];
+
+ let description = [{
+ The `bind` clause specifies the binding region of the construct on which it
+ appears.
+ }];
+}
+
+def OpenMP_BindClause : OpenMP_BindClauseSkip<>;
+
+//===----------------------------------------------------------------------===//
// V5.2: [5.7.2] `copyprivate` clause
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 5fd8184..a0da3db1 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -382,6 +382,50 @@ def LoopNestOp : OpenMP_Op<"loop_nest", traits = [
// 2.9.2 Workshare Loop Construct
//===----------------------------------------------------------------------===//
+def LoopOp : OpenMP_Op<"loop", traits = [
+ AttrSizedOperandSegments, DeclareOpInterfaceMethods<LoopWrapperInterface>,
+ NoTerminator, SingleBlock
+ ], clauses = [
+ OpenMP_BindClause, OpenMP_PrivateClause, OpenMP_OrderClause,
+ OpenMP_ReductionClause
+ ], singleRegion = true> {
+ let summary = "loop construct";
+ let description = [{
+ A loop construct specifies that the logical iterations of the associated loops
+ may execute concurrently and permits the encountering threads to execute the
+ loop accordingly. A loop construct can have 3 different types of binding:
+ 1. teams: in which case the binding region is the innermost enclosing `teams`
+ region.
+ 2. parallel: in which case the binding region is the innermost enclosing `parallel`
+ region.
+ 3. thread: in which case the binding region is not defined.
+
+ The body region can only contain a single block which must contain a single
+ operation, this operation must be an `omp.loop_nest`.
+
+ ```
+ omp.loop <clauses> {
+ omp.loop_nest (%i1, %i2) : index = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) {
+ %a = load %arrA[%i1, %i2] : memref<?x?xf32>
+ %b = load %arrB[%i1, %i2] : memref<?x?xf32>
+ %sum = arith.addf %a, %b : f32
+ store %sum, %arrC[%i1, %i2] : memref<?x?xf32>
+ omp.yield
+ }
+ }
+ ```
+ }] # clausesDescription;
+
+ let assemblyFormat = clausesAssemblyFormat # [{
+ custom<PrivateReductionRegion>($region, $private_vars, type($private_vars),
+ $private_syms, $reduction_vars, type($reduction_vars), $reduction_byref,
+ $reduction_syms) attr-dict
+ }];
+
+ let hasVerifier = 1;
+ let hasRegionVerifier = 1;
+}
+
def WsloopOp : OpenMP_Op<"wsloop", traits = [
AttrSizedOperandSegments, DeclareOpInterfaceMethods<ComposableOpInterface>,
DeclareOpInterfaceMethods<LoopWrapperInterface>, NoTerminator,
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 4a27a5e..228c2d0 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -1949,6 +1949,23 @@ LogicalResult LoopWrapperInterface::verifyImpl() {
}
//===----------------------------------------------------------------------===//
+// LoopOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult LoopOp::verify() {
+ return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
+ getReductionByref());
+}
+
+LogicalResult LoopOp::verifyRegions() {
+ if (llvm::isa_and_nonnull<LoopWrapperInterface>((*this)->getParentOp()) ||
+ getNestedWrapper())
+ return emitError() << "`omp.loop` expected to be a standalone loop wrapper";
+
+ return success();
+}
+
+//===----------------------------------------------------------------------===//
// WsloopOp
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index db941d40..aa41eea 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -2577,3 +2577,49 @@ func.func @omp_taskloop_invalid_composite(%lb: index, %ub: index, %step: index)
} {omp.composite}
return
}
+
+// -----
+
+func.func @omp_loop_invalid_nesting(%lb : index, %ub : index, %step : index) {
+
+ // expected-error @below {{`omp.loop` expected to be a standalone loop wrapper}}
+ omp.loop {
+ omp.simd {
+ omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+ omp.yield
+ }
+ } {omp.composite}
+ }
+
+ return
+}
+
+// -----
+
+func.func @omp_loop_invalid_nesting2(%lb : index, %ub : index, %step : index) {
+
+ omp.simd {
+ // expected-error @below {{`omp.loop` expected to be a standalone loop wrapper}}
+ omp.loop {
+ omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+ omp.yield
+ }
+ } {omp.composite}
+ }
+
+ return
+}
+
+// -----
+
+func.func @omp_loop_invalid_binding(%lb : index, %ub : index, %step : index) {
+
+ // expected-error @below {{custom op 'omp.loop' invalid clause value: 'dummy_value'}}
+ omp.loop bind(dummy_value) {
+ omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+ omp.yield
+ }
+ }
+
+ return
+}
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index b606f9e..4f5cc69 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -2749,3 +2749,43 @@ func.func @omp_target_private(%map1: memref<?xi32>, %map2: memref<?xi32>, %priv_
return
}
+
+// CHECK-LABEL: omp_loop
+func.func @omp_loop(%lb : index, %ub : index, %step : index) {
+ // CHECK: omp.loop {
+ omp.loop {
+ // CHECK: omp.loop_nest {{.*}} {
+ omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+ // CHECK: omp.yield
+ omp.yield
+ }
+ // CHECK: }
+ }
+ // CHECK: }
+
+ // CHECK: omp.loop bind(teams) {
+ omp.loop bind(teams) {
+ omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+ omp.yield
+ }
+ }
+ // CHECK: }
+
+ // CHECK: omp.loop bind(parallel) {
+ omp.loop bind(parallel) {
+ omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+ omp.yield
+ }
+ }
+ // CHECK: }
+
+ // CHECK: omp.loop bind(thread) {
+ omp.loop bind(thread) {
+ omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
+ omp.yield
+ }
+ }
+ // CHECK: }
+
+ return
+}