diff --git a/mlir/include/mlir/Dialect/OpenMP/CMakeLists.txt b/mlir/include/mlir/Dialect/OpenMP/CMakeLists.txt --- a/mlir/include/mlir/Dialect/OpenMP/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/OpenMP/CMakeLists.txt @@ -1,2 +1,8 @@ -add_mlir_dialect(OpenMPOps omp) +set(LLVM_TARGET_DEFINITIONS OpenMPOps.td) +mlir_tablegen(OpenMPOpsDialect.h.inc -gen-dialect-decls -dialect=omp) +mlir_tablegen(OpenMPOps.h.inc -gen-op-decls) +mlir_tablegen(OpenMPOps.cpp.inc -gen-op-defs) +mlir_tablegen(OpenMPOpsEnums.h.inc -gen-enum-decls) +mlir_tablegen(OpenMPOpsEnums.cpp.inc -gen-enum-defs) add_mlir_doc(OpenMPOps -gen-dialect-doc OpenMPDialect Dialects/) +add_public_tablegen_target(MLIROpenMPOpsIncGen) diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h b/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.h @@ -16,6 +16,8 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/OpDefinition.h" +#include "mlir/Dialect/OpenMP/OpenMPOpsEnums.h.inc" + namespace mlir { namespace omp { diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -18,31 +18,79 @@ def OpenMP_Dialect : Dialect { let name = "omp"; + let cppNamespace = "omp"; } class OpenMP_Op traits = []> : Op; -def BarrierOp : OpenMP_Op<"barrier"> { - let summary = "barrier construct"; + +//===----------------------------------------------------------------------===// +// 2.6 parallel Construct +//===----------------------------------------------------------------------===// + +// Possible values for the default clause +def ClauseDefaultPrivate : StrEnumAttrCase<"defprivate">; +def ClauseDefaultFirstPrivate : StrEnumAttrCase<"deffirstprivate">; +def ClauseDefaultShared : StrEnumAttrCase<"defshared">; +def ClauseDefaultNone : StrEnumAttrCase<"defnone">; + +def ClauseDefault : StrEnumAttr< + "ClauseDefault", + "default clause", + [ClauseDefaultPrivate, ClauseDefaultFirstPrivate, ClauseDefaultShared, + ClauseDefaultNone]> { + let cppNamespace = "::mlir::omp"; +} + +// Possible values for the proc_bind clause +def ClauseProcMaster : StrEnumAttrCase<"master">; +def ClauseProcClose : StrEnumAttrCase<"close">; +def ClauseProcSpread : StrEnumAttrCase<"spread">; + +def ClauseProcBind : StrEnumAttr< + "ClauseProcBind", + "procbind clause", + [ClauseProcMaster, ClauseProcClose, ClauseProcSpread]> { + let cppNamespace = "::mlir::omp"; +} + +def ParallelOp : OpenMP_Op<"parallel", [AttrSizedOperandSegments]> { + let summary = "parallel construct"; let description = [{ - The barrier construct specifies an explicit barrier at the point at which - the construct appears. + The parallel construct includes a region of code which is to be executed + by a team of threads. }]; - let assemblyFormat = "attr-dict"; + let arguments = (ins Optional:$if_expr_var, + Optional:$num_threads_var, + OptionalAttr:$default_val, + Variadic:$private_vars, + Variadic:$firstprivate_vars, + Variadic:$shared_vars, + Variadic:$copyin_vars, + OptionalAttr:$proc_bind_val); + + let regions = (region AnyRegion:$region); } -def TaskwaitOp : OpenMP_Op<"taskwait"> { - let summary = "taskwait construct"; +def TerminatorOp : OpenMP_Op<"terminator", [Terminator]> { + let summary = "terminator for OpenMP regions."; let description = [{ - The taskwait construct specifies a wait on the completion of child tasks - of the current task. + A terminator operation for regions that appear in the body of OpenMP + operation. These regions are not expected to return any value so the + terminator takes no operands. The terminator op returns control to the + enclosing op. }]; - let assemblyFormat = "attr-dict"; + let parser = [{ return success(); }]; + let printer = [{ p << getOperationName(); }]; } +//===----------------------------------------------------------------------===// +// 2.10.4 taskyield Construct +//===----------------------------------------------------------------------===// + def TaskyieldOp : OpenMP_Op<"taskyield"> { let summary = "taskyield construct"; let description = [{ @@ -53,4 +101,32 @@ let assemblyFormat = "attr-dict"; } +//===----------------------------------------------------------------------===// +// 2.17.2 barrier Construct +//===----------------------------------------------------------------------===// + +def BarrierOp : OpenMP_Op<"barrier"> { + let summary = "barrier construct"; + let description = [{ + The barrier construct specifies an explicit barrier at the point at which + the construct appears. + }]; + + let assemblyFormat = "attr-dict"; +} + +//===----------------------------------------------------------------------===// +// 2.17.5 taskwait Construct +//===----------------------------------------------------------------------===// + +def TaskwaitOp : OpenMP_Op<"taskwait"> { + let summary = "taskwait construct"; + let description = [{ + The taskwait construct specifies a wait on the completion of child tasks + of the current task. + }]; + + let assemblyFormat = "attr-dict"; +} + #endif // OPENMP_OPS diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -11,8 +11,13 @@ //===----------------------------------------------------------------------===// #include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/Dialect/StandardOps/IR/Ops.h" #include "mlir/IR/OpImplementation.h" +#include "llvm/ADT/StringSwitch.h" + +#include "mlir/Dialect/OpenMP/OpenMPOpsEnums.cpp.inc" + using namespace mlir; using namespace mlir::omp; diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -17,3 +17,39 @@ omp.taskyield return } + +func @omp_terminator() -> () { + // CHECK: omp.terminator + omp.terminator +} + +func @omp_parallel(%data_var : memref, %if_cond : i1, %num_threads : si32) -> () { + // CHECK: omp_parallel + "omp.parallel" (%if_cond, %num_threads, %data_var, %data_var, %data_var, %data_var) ({ + + // test without if condition + // CHECK: omp.parallel + "omp.parallel"(%num_threads, %data_var, %data_var, %data_var, %data_var) ({ + omp.terminator + }) {operand_segment_sizes = dense<[0,1,1,1,1,1]>: vector<6xi32>, default_val = "defshared"} : (si32, memref, memref, memref, memref) -> () + + // CHECK: omp.barrier + omp.barrier + + // test without num_threads + // CHECK: omp.parallel + "omp.parallel"(%if_cond, %data_var, %data_var, %data_var, %data_var) ({ + omp.terminator + }) {operand_segment_sizes = dense<[1,0,1,1,1,1]> : vector<6xi32>} : (i1, memref, memref, memref, memref) -> () + + omp.terminator + }) {operand_segment_sizes = dense<[1,1,1,1,1,1]> : vector<6xi32>, proc_bind_val = "spread"} : (i1, si32, memref, memref, memref, memref) -> () + + // test with multiple parameters for single variadic argument + // CHECK: omp.parallel + "omp.parallel" (%data_var, %data_var, %data_var, %data_var, %data_var) ({ + omp.terminator + }) {operand_segment_sizes = dense<[0,0,1,2,1,1]> : vector<6xi32>} : (memref, memref, memref, memref, memref) -> () + + return +}