[Mlir-commits] [mlir] [MLIR][OpenMP] Add verification for DeclareTargetInterface (PR #217294)
Sergio Afonso
llvmlistbot at llvm.org
Mon Aug 24 04:19:01 PDT 2026
https://github.com/skatrak updated https://github.com/llvm/llvm-project/pull/217294
>From 3f93b1609779138f5d14f21d32137dd5160414e8 Mon Sep 17 00:00:00 2001
From: Sergio Afonso <Sergio.AfonsoFumero at amd.com>
Date: Mon, 17 Aug 2026 14:29:19 +0100
Subject: [PATCH] [MLIR][OpenMP] Add verification for DeclareTargetInterface
This patch introduces checks to ensure the "omp.declare_target"
attribute is only attached to `DeclareTargetInterface` operations, it is
always the right type attribute and its properties do not conflict with
the operation they are attached to.
---
.../mlir/Dialect/OpenMP/OpenMPDialect.td | 1 +
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 42 +++++++++++++++++++
mlir/test/Dialect/OpenMP/attr.mlir | 18 --------
.../Dialect/OpenMP/invalid-interface.mlir | 28 +++++++++++++
4 files changed, 71 insertions(+), 18 deletions(-)
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.td
index 8ef8fcccf2d57..dbc851a5e297c 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.td
@@ -18,6 +18,7 @@ def OpenMP_Dialect : Dialect {
let useDefaultAttributePrinterParser = 1;
let useStrictPropertiesInAssemblyFormat = 1;
let useDefaultTypePrinterParser = 1;
+ let hasOperationAttrVerify = 1;
}
#endif // OPENMP_DIALECT
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index c957321771ab7..f06c665c7013b 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -343,6 +343,48 @@ void OpenMPDialect::initialize() {
mlir::omp::DeclareTargetDefaultModel<mlir::func::FuncOp>>(*getContext());
}
+//===----------------------------------------------------------------------===//
+// Dialect operation attribute verification
+//===----------------------------------------------------------------------===//
+
+static LogicalResult verifyDeclareTargetAttr(Operation *op, Attribute attr) {
+ if (!isa<DeclareTargetInterface>(op))
+ return op->emitError() << "omp.declare_target can only be applied to "
+ "DeclareTargetInterface ops";
+
+ auto declareTargetAttr = dyn_cast<DeclareTargetAttr>(attr);
+ if (!declareTargetAttr)
+ return op->emitError()
+ << "omp.declare_target must be an #omp.declaretarget attribute";
+
+ if (isa<mlir::FunctionOpInterface>(op)) {
+ if (declareTargetAttr.getAutomap())
+ return op->emitOpError()
+ << "omp.declare_target 'automap' is not valid on functions";
+
+ // TODO: Disallow the `local` clause (OpenMP 6.0).
+ if (declareTargetAttr.getCaptureClause().getValue() ==
+ mlir::omp::DeclareTargetCaptureClause::link)
+ return op->emitOpError()
+ << "omp.declare_target 'link' is not valid on functions";
+ } else {
+ // TODO: Disallow the `indirect` clause (OpenMP 5.1).
+ if (declareTargetAttr.getImplicit())
+ return op->emitOpError()
+ << "omp.declare_target 'implicit' is only valid on functions";
+ }
+ return success();
+}
+
+LogicalResult
+OpenMPDialect::verifyOperationAttribute(Operation *op,
+ NamedAttribute attribute) {
+ if (attribute.getName() == "omp.declare_target")
+ return verifyDeclareTargetAttr(op, attribute.getValue());
+
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// Parser and printer for Allocate Clause
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/OpenMP/attr.mlir b/mlir/test/Dialect/OpenMP/attr.mlir
index 61a4e0df2f1ff..8c6f25f3bcaab 100644
--- a/mlir/test/Dialect/OpenMP/attr.mlir
+++ b/mlir/test/Dialect/OpenMP/attr.mlir
@@ -71,12 +71,6 @@ func.func @omp_decl_tar_host_to() -> () attributes {omp.declare_target = #omp.de
return
}
-// CHECK-LABEL: func @omp_decl_tar_host_link
-// CHECK-SAME: {{.*}} attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (link)>} {
-func.func @omp_decl_tar_host_link() -> () attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (link)>} {
- return
-}
-
// CHECK-LABEL: func @omp_decl_tar_host_enter
// CHECK-SAME: {{.*}} attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (enter)>} {
func.func @omp_decl_tar_host_enter() -> () attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (enter)>} {
@@ -89,12 +83,6 @@ func.func @omp_decl_tar_nohost_to() -> () attributes {omp.declare_target = #omp.
return
}
-// CHECK-LABEL: func @omp_decl_tar_nohost_link
-// CHECK-SAME: {{.*}} attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (link)>} {
-func.func @omp_decl_tar_nohost_link() -> () attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (link)>} {
- return
-}
-
// CHECK-LABEL: func @omp_decl_tar_nohost_enter
// CHECK-SAME: {{.*}} attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter)>} {
func.func @omp_decl_tar_nohost_enter() -> () attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter)>} {
@@ -107,12 +95,6 @@ func.func @omp_decl_tar_any_to() -> () attributes {omp.declare_target = #omp.dec
return
}
-// CHECK-LABEL: func @omp_decl_tar_any_link
-// CHECK-SAME: {{.*}} attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>} {
-func.func @omp_decl_tar_any_link() -> () attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>} {
- return
-}
-
// CHECK-LABEL: func @omp_decl_tar_any_enter
// CHECK-SAME: {{.*}} attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>} {
func.func @omp_decl_tar_any_enter() -> () attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>} {
diff --git a/mlir/test/Dialect/OpenMP/invalid-interface.mlir b/mlir/test/Dialect/OpenMP/invalid-interface.mlir
index 6fe64b0839e66..787b6a7ec00ce 100644
--- a/mlir/test/Dialect/OpenMP/invalid-interface.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid-interface.mlir
@@ -104,3 +104,31 @@ func.func @composable_conditional_combined(%x : i32) {
} {omp.combined}
return
}
+
+// -----
+
+// expected-error @below {{omp.declare_target can only be applied to DeclareTargetInterface ops}}
+%0 = arith.constant { omp.declare_target = #omp.declaretarget<capture_clause = (enter)> } 2 : i32
+
+// -----
+
+// expected-error @below {{omp.declare_target must be an #omp.declaretarget attribute}}
+func.func private @declare_target_attr_type() attributes { omp.declare_target = 10 : i32 }
+
+// -----
+
+// expected-error @below {{omp.declare_target 'automap' is not valid on functions}}
+func.func private @declare_target_automap() attributes { omp.declare_target = #omp.declaretarget<automap = true>}
+
+// -----
+
+// expected-error @below {{omp.declare_target 'link' is not valid on functions}}
+func.func private @declare_target_link() attributes { omp.declare_target = #omp.declaretarget<capture_clause = (link)>}
+
+// -----
+
+// expected-error @below {{omp.declare_target 'implicit' is only valid on functions}}
+llvm.mlir.global @declare_target_implicit() {omp.declare_target = #omp.declaretarget<implicit = true>} : i32 {
+ %0 = llvm.mlir.constant(1 : i32) : i32
+ llvm.return %0 : i32
+}
More information about the Mlir-commits
mailing list