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 @@ -1692,4 +1692,35 @@ let hasVerifier = 1; } +//===----------------------------------------------------------------------===// +// 8.2 requires directive +//===----------------------------------------------------------------------===// + +// atomic_default_mem_order clause values not defined here because they can be +// represented by the OMPC_MemoryOrder enumeration instead. +def ClauseRequiresNone : I32BitEnumAttrCaseNone<"none">; +def ClauseRequiresReverseOffload : I32BitEnumAttrCaseBit<"reverse_offload", 0>; +def ClauseRequiresUnifiedAddress : I32BitEnumAttrCaseBit<"unified_address", 1>; +def ClauseRequiresUnifiedSharedMemory + : I32BitEnumAttrCaseBit<"unified_shared_memory", 2>; +def ClauseRequiresDynamicAllocators + : I32BitEnumAttrCaseBit<"dynamic_allocators", 3>; + +def ClauseRequires : I32BitEnumAttr< + "ClauseRequires", + "requires clauses", + [ + ClauseRequiresNone, + ClauseRequiresReverseOffload, + ClauseRequiresUnifiedAddress, + ClauseRequiresUnifiedSharedMemory, + ClauseRequiresDynamicAllocators + ]> { + let genSpecializedAttr = 0; + let cppNamespace = "::mlir::omp"; +} +def ClauseRequiresAttr : + EnumAttr { +} + #endif // OPENMP_OPS diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td @@ -136,7 +136,7 @@ mlir::StringAttr::get($_op->getContext(), llvm::Twine{"omp.is_device"}), mlir::BoolAttr::get($_op->getContext(), isDevice)); }]>, - InterfaceMethod< + InterfaceMethod< /*description=*/[{ Get the attribute on the current module if it exists and return its value, if it doesn't exist it returns false by default. @@ -149,7 +149,7 @@ return isDevice.dyn_cast().getValue(); return false; }]>, - InterfaceMethod< + InterfaceMethod< /*description=*/[{ Get the FlagsAttr attribute on the current module if it exists and return the attribute, if it doesn't exit it returns a nullptr @@ -207,7 +207,7 @@ targetCPU.str(), targetFeatures.str())); }]>, - InterfaceMethod< + InterfaceMethod< /*description=*/[{ Set a StringAttr on the current module containing the host IR file path. This file path is used in two-phase compilation during the device phase to generate @@ -220,7 +220,7 @@ mlir::StringAttr::get($_op->getContext(), llvm::Twine{"omp.host_ir_filepath"}), mlir::StringAttr::get($_op->getContext(), hostIRFilePath)); }]>, - InterfaceMethod< + InterfaceMethod< /*description=*/[{ Find the host-ir file path StringAttr from the current module if it exists and return its contained value, if it doesn't exist it returns an empty string. This @@ -234,6 +234,30 @@ if (::llvm::isa(filepath)) return ::llvm::dyn_cast(filepath).getValue(); return {}; + }]>, + InterfaceMethod< + /*description=*/[{ + Get the omp.requires attribute on the operator if it's present and + return its value. If it doesn't exist, return `ClauseRequires::none` by + default. + }], + /*retTy=*/"::mlir::omp::ClauseRequires", + /*methodName=*/"getRequires", + (ins), [{}], [{ + if (Attribute requiresAttr = $_op->getAttr("omp.requires")) + if (auto requiresVal = requiresAttr.dyn_cast()) + return requiresVal.getValue(); + return mlir::omp::ClauseRequires::none; + }]>, + InterfaceMethod< + /*description=*/[{ + Set the omp.requires attribute on the operator to the specified clauses. + }], + /*retTy=*/"void", + /*methodName=*/"setRequires", + (ins "::mlir::omp::ClauseRequires":$clauses), [{}], [{ + $_op->setAttr(mlir::StringAttr::get($_op->getContext(), "omp.requires"), + mlir::omp::ClauseRequiresAttr::get($_op->getContext(), clauses)); }]> ]; } 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 @@ -1881,6 +1881,20 @@ return } +// CHECK: func.func @omp_requires_one +// CHECK-SAME: omp.requires = #omp +func.func @omp_requires_one() -> () + attributes {omp.requires = #omp} { + return +} + +// CHECK: func.func @omp_requires_multiple +// CHECK-SAME: omp.requires = #omp +func.func @omp_requires_multiple() -> () + attributes {omp.requires = #omp} { + return +} + // ----- // CHECK-LABEL: @opaque_pointers_atomic_rwu