Index: mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td =================================================================== --- mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -965,6 +965,59 @@ `map` `(` custom($map_operands, type($map_operands), $map_types) `)` attr-dict }]; + + let hasVerifier = 1; +} + +//===----------------------------------------------------------------------===// +// 2.12.7 declare target directive +//===----------------------------------------------------------------------===// + +def ClauseDeviceTypeAny : I32EnumAttrCase<"devicetypeany", 0>; +def ClauseDeviceTypeHost : I32EnumAttrCase<"devicetypehost", 1>; +def ClauseDeviceTypeNoHost : I32EnumAttrCase<"devicetypenohost", 2>; + +def ClauseDeviceType : I32EnumAttr< + "ClauseDeviceType", + "device_type clause", + [ClauseDeviceTypeAny, ClauseDeviceTypeHost, ClauseDeviceTypeNoHost]> { + let genSpecializedAttr = 0; + let cppNamespace = "::mlir::omp"; +} +def ClauseDeviceTypeAttr : EnumAttr { + let assemblyFormat = "`(` $value `)`"; +} + +def TargetDeclareOp : OpenMP_Op<"target.declare"> { + let summary = "declare target directive"; + let description = [{ + The declare target directive specifies that variables, functions (C, C++ and Fortran), + and subroutines (Fortran) are mapped to a device. The declare target directive is a + declarative directive. + + The $device_type argument contains an integer from 0 to 2, which specifies + one of the three options that can be given to the device_type clause (e.g. + host | nohost | any). + + The $to_operands argument contains symbol references for functions and + global variables captured by the "to" clause of declare target or explicitly + captured via brackets e.g: declare target(var1, var2), the device type is + implicitly expected to be any. + + The $link_operands argument contains symbol references for functions and global + variables captured by the "link" clause of declare target e.g: declare target + link(var1, var2). The device type is explicitly specified by the link clause. + }]; + + let arguments = (ins ClauseDeviceTypeAttr:$device_type, + OptionalAttr:$to_operands, + OptionalAttr:$link_operands); + + let assemblyFormat = [{ + oilist( `to` `(` $to_operands `)` + | `link` `(` $link_operands `)` + ) `device_type` `` $device_type attr-dict + }]; let hasVerifier = 1; } Index: mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp =================================================================== --- mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -1346,6 +1346,24 @@ return success(); } +//===----------------------------------------------------------------------===// +// Verifier for TargetDeclareOp +//===----------------------------------------------------------------------===// + +LogicalResult TargetDeclareOp::verify() { + auto toOps = getToOperands(); + auto linkOps = getLinkOperands(); + + // The operation should have at least one item in either operand list (there + // should be at least one implicit capture), otherwise the op is essentially a + // no-op + if ((!toOps || toOps->empty()) && (!linkOps || linkOps->empty())) + return emitOpError() + << "The TargetDeclareOp must have ToOperands or LinkOperands"; + + return success(); +} + #define GET_ATTRDEF_CLASSES #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc" Index: mlir/test/Dialect/OpenMP/ops.mlir =================================================================== --- mlir/test/Dialect/OpenMP/ops.mlir +++ mlir/test/Dialect/OpenMP/ops.mlir @@ -1860,3 +1860,39 @@ // CHECK: return return } + +// CHECK-LABEL: omp_target_declare +func.func @omp_target_declare () -> () { + // CHECK: omp.target.declare to([@omp_target_declare, @add_f32]) link([@add_f32, @omp_target_declare]) device_type(devicetypehost) + omp.target.declare to([@omp_target_declare, @add_f32]) link([@add_f32, @omp_target_declare]) device_type(devicetypehost) + // CHECK: omp.target.declare to([@omp_target_declare, @add_f32]) link([@add_f32, @omp_target_declare]) device_type(devicetypeany) + omp.target.declare to([@omp_target_declare, @add_f32]) link([@add_f32, @omp_target_declare]) device_type(devicetypeany) + // CHECK: omp.target.declare to([@omp_target_declare, @add_f32]) link([@add_f32, @omp_target_declare]) device_type(devicetypenohost) + omp.target.declare to([@omp_target_declare, @add_f32]) link([@add_f32, @omp_target_declare]) device_type(devicetypenohost) + // CHECK: omp.target.declare to([@omp_target_declare, @add_f32]) device_type(devicetypehost) + omp.target.declare to([@omp_target_declare, @add_f32]) device_type(devicetypehost) + // CHECK: omp.target.declare to([@omp_target_declare, @add_f32]) device_type(devicetypeany) + omp.target.declare to([@omp_target_declare, @add_f32]) device_type(devicetypeany) + // CHECK: omp.target.declare to([@omp_target_declare, @add_f32]) device_type(devicetypenohost) + omp.target.declare to([@omp_target_declare, @add_f32]) device_type(devicetypenohost) + // CHECK: omp.target.declare link([@omp_target_declare, @add_f32]) device_type(devicetypehost) + omp.target.declare link([@omp_target_declare, @add_f32]) device_type(devicetypehost) + // CHECK: omp.target.declare link([@omp_target_declare, @add_f32]) device_type(devicetypeany) + omp.target.declare link([@omp_target_declare, @add_f32]) device_type(devicetypeany) + // CHECK: omp.target.declare link([@omp_target_declare, @add_f32]) device_type(devicetypenohost) + omp.target.declare link([@omp_target_declare, @add_f32]) device_type(devicetypenohost) + // CHECK: omp.target.declare to([@omp_target_declare]) device_type(devicetypehost) + omp.target.declare to([@omp_target_declare]) device_type(devicetypehost) + // CHECK: omp.target.declare to([@omp_target_declare]) device_type(devicetypeany) + omp.target.declare to([@omp_target_declare]) device_type(devicetypeany) + // CHECK: omp.target.declare to([@omp_target_declare]) device_type(devicetypenohost) + omp.target.declare to([@omp_target_declare]) device_type(devicetypenohost) + // CHECK: omp.target.declare link([@omp_target_declare]) device_type(devicetypehost) + omp.target.declare link([@omp_target_declare]) device_type(devicetypehost) + // CHECK: omp.target.declare link([@omp_target_declare]) device_type(devicetypeany) + omp.target.declare link([@omp_target_declare]) device_type(devicetypeany) + // CHECK: omp.target.declare link([@omp_target_declare]) device_type(devicetypenohost) + omp.target.declare link([@omp_target_declare]) device_type(devicetypenohost) + + return +}