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,16 +18,103 @@ 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. + + The optional $if_expr_var parameter specifies a boolean result of a + conditional check. If this value is 1 or is not provided then the parallel + region runs as normal, if it is 0 then the parallel region is executed with + one thread. + + The optional $num_threads_var parameter specifies the number of threads which + should be used to execute the parallel region. + + The optional $default_val attribute specifies the default data sharing attribute + of variables used in the parallel region that are not passed explicitly as parameters + to the operation. + + The $private_vars, $firstprivate_vars, $shared_vars and $copyin_vars parameters + are a variadic list of variables that specify the data sharing attribute of + those variables. + + The optional $proc_bind_val attribute controls the thread affinity for the execution + of the parallel region. + }]; + + 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 TerminatorOp : OpenMP_Op<"terminator", [Terminator]> { + let summary = "terminator for OpenMP regions."; + let description = [{ + 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 parser = [{ return success(); }]; + let printer = [{ p << getOperationName(); }]; +} + +//===----------------------------------------------------------------------===// +// 2.10.4 taskyield Construct +//===----------------------------------------------------------------------===// + +def TaskyieldOp : OpenMP_Op<"taskyield"> { + let summary = "taskyield construct"; + let description = [{ + The taskyield construct specifies that the current task can be suspended + in favor of execution of a different task. }]; let assemblyFormat = "attr-dict"; @@ -50,21 +137,29 @@ let assemblyFormat = "attr-dict ($varList^ `:` type($varList))?"; } -def TaskwaitOp : OpenMP_Op<"taskwait"> { - let summary = "taskwait construct"; +//===----------------------------------------------------------------------===// +// 2.17.2 barrier Construct +//===----------------------------------------------------------------------===// + +def BarrierOp : OpenMP_Op<"barrier"> { + let summary = "barrier construct"; let description = [{ - The taskwait construct specifies a wait on the completion of child tasks - of the current task. + The barrier construct specifies an explicit barrier at the point at which + the construct appears. }]; let assemblyFormat = "attr-dict"; } -def TaskyieldOp : OpenMP_Op<"taskyield"> { - let summary = "taskyield construct"; +//===----------------------------------------------------------------------===// +// 2.17.5 taskwait Construct +//===----------------------------------------------------------------------===// + +def TaskwaitOp : OpenMP_Op<"taskwait"> { + let summary = "taskwait construct"; let description = [{ - The taskyield construct specifies that the current task can be suspended - in favor of execution of a different task. + The taskwait construct specifies a wait on the completion of child tasks + of the current task. }]; let assemblyFormat = "attr-dict"; 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 @@ -35,3 +35,39 @@ 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 +}