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,6 +18,7 @@ def OpenMP_Dialect : Dialect { let name = "omp"; + let cppNamespace = "omp"; } class OpenMP_Op traits = []> : @@ -53,4 +54,61 @@ let assemblyFormat = "attr-dict"; } +def ClauseDefaultPrivate : StrEnumAttrCase<"defprivate">; +def ClauseDefaultFirstPrivate : StrEnumAttrCase<"deffirstprivate">; +def ClauseDefaultShared : StrEnumAttrCase<"defshared">; +def ClauseDefaultNone : StrEnumAttrCase<"defnone">; + +def ClauseProcMaster : StrEnumAttrCase<"master">; +def ClauseProcClose : StrEnumAttrCase<"close">; +def ClauseProcSpread : StrEnumAttrCase<"spread">; + +def ClauseDefault : StrEnumAttr< + "ClauseDefault", + "default clause", + [ClauseDefaultPrivate, ClauseDefaultFirstPrivate, ClauseDefaultShared, ClauseDefaultNone]> { + let cppNamespace = "::mlir::omp"; +} + +def ClauseProcBind : StrEnumAttr< + "ClauseProcBind", + "procbind clause", + [ClauseProcMaster, ClauseProcClose, ClauseProcSpread]> { + let cppNamespace = "::mlir::omp"; +} + +def ParallelOp : OpenMP_Op<"parallel", [AttrSizedOperandSegments]>, + 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 summary = "parallel construct"; + let description = [{ + The parallel construct includes a region of code which is to be executed + by a team of threads. + }]; + + let regions = (region AnyRegion:$region); + let parser = [{ return parseParallelOp(parser, result); }]; + let printer = [{ printParallelOp(p, *this); }]; +} + +def TerminatorOp : OpenMP_Op<"terminator", [Terminator]>, + Arguments<(ins)>, Results<(outs)> { + 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(); }]; +} + #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; @@ -24,6 +29,51 @@ >(); } +static ParseResult parseParallelOp(OpAsmParser &parser, + OperationState &result) { + SmallVector operands; + + // Parse operand list + if (parser.parseOperandList(operands)) + return failure(); + // If attributes are present, parse them. + if (parser.parseOptionalAttrDictWithKeyword(result.attributes)) + return failure(); + + // Parse the module body. + auto *body = result.addRegion(); + if (parser.parseRegion(*body, None, None)) + return failure(); + + Type type; + if (parser.parseColon() || parser.parseType(type)) + return failure(); + result.addTypes(type); + + return success(); +} + +static void printParallelOp(OpAsmPrinter &p, ParallelOp op) { + p << op.getOperationName() << ' '; + p << '('; + bool first = true; + for (auto value : op.getOperands()) { + if (first) { + first = false; + } else { + p << ", "; + } + p << value << " : " << value.getType(); + } + p << ')'; + p.printOptionalAttrDictWithKeyword(op.getAttrs(), + {SymbolTable::getSymbolAttrName()}); + p.printRegion(op.getOperation()->getRegion(0), /*printEntryBlockArgs=*/false, + /*printBlockTerminators=*/false); + + // p << ": " << op.type(); +} + namespace mlir { namespace omp { #define GET_OP_CLASSES 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,33 @@ omp.taskyield return } + +func @omp_terminator() -> () { + // CHECK: omp.terminator + omp.terminator +} + +func @omp_parallel(%t : memref, %b : i1, %i : si32) -> () { + // CHECK: omp_parallel + "omp.parallel" (%b, %i, %t, %t, %t, %t) ({ + // test without if condition + // CHECK: omp.parallel + "omp.parallel"(%i, %t, %t, %t, %t) ({ + omp.terminator + }) {operand_segment_sizes = dense<[0,1,1,1,1,1]>: vector<6xi32>} : (si32, memref, memref, memref, memref) -> () + omp.barrier + // test without num_threads + // CHECK: omp.barrier + "omp.parallel"(%b, %t, %t, %t, %t) ({ + // CHECK: omp.parallel + 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" (%t, %t, %t, %t, %t) ({ + omp.terminator + }) {operand_segment_sizes = dense<[0,0,1,2,1,1]> : vector<6xi32>} : (memref, memref, memref, memref, memref) -> () + return +}