[flang-commits] [clang] [flang] [mlir] [MLIR][OpenMP] DeclareTargetInterface and DeclareTargetAttr cleanup (PR #217295)

Sergio Afonso via flang-commits flang-commits at lists.llvm.org
Thu Sep 3 08:59:01 PDT 2026


https://github.com/skatrak updated https://github.com/llvm/llvm-project/pull/217295

>From 2e1201fb30537e590dd2c252269777e0efe9be52 Mon Sep 17 00:00:00 2001
From: Sergio Afonso <Sergio.AfonsoFumero at amd.com>
Date: Tue, 18 Aug 2026 11:49:55 +0100
Subject: [PATCH] [MLIR][OpenMP] DeclareTargetInterface and DeclareTargetAttr
 cleanup

The changes introduced by this patch are intended to avoid triggering
multiple by name lookups to the "omp.declare_target" attribute every
time any data from the `DeclareTargetInterface` is queried, remove the
need for keeping multiple default values for the same data, clean up
the assembly format and generally improve the usage of the interface.

List of changes:
- `DeclareTargetInterface` only provides `setDeclareTarget` and
  `getDeclareTarget` methods to handle the "omp.declare_target"
  attribute, maintaining a single canonical way of accessing it.
- `DeclareTargetAttr` provides direct access to the capture clause and
  device type enums, rather than wrapping them into an `Attribute`.
  These are now mandatory as well. Both changes together make accessing
  them more straightforward and simplify the attribute representation.
---
 .../CodeGenOpenMP/emit-device-functions.cpp   |  2 +-
 .../Transforms/omp-mark-declare-target.cir    |  8 +-
 flang/docs/OpenMP-declare-target.md           |  7 +-
 flang/lib/Lower/OpenMP/OpenMP.cpp             | 13 ++--
 .../Optimizer/OpenMP/AutomapToTargetData.cpp  |  8 +-
 .../OpenMP/UnimplementedDeviceCheck.cpp       |  7 +-
 .../OpenMP/declare-target-funcs.f90           |  4 +-
 .../declare-target-named-main-interface.f90   |  2 +-
 .../OpenMP/declare-target-multiple-entry.f90  |  6 +-
 .../mlir/Dialect/OpenMP/OpenMPAttrDefs.td     |  4 +-
 .../Dialect/OpenMP/OpenMPOpsInterfaces.td     | 76 ++++---------------
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  |  2 +-
 .../OpenMP/Transforms/FunctionFiltering.cpp   |  8 +-
 .../OpenMP/Transforms/HostOpFiltering.cpp     |  6 +-
 .../OpenMP/Transforms/MarkDeclareTarget.cpp   | 16 ++--
 mlir/lib/Dialect/OpenMP/Utils/Utils.cpp       |  7 +-
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      | 44 ++++++-----
 .../Dialect/OpenMP/invalid-interface.mlir     |  8 +-
 18 files changed, 103 insertions(+), 125 deletions(-)

diff --git a/clang/test/CIR/CodeGenOpenMP/emit-device-functions.cpp b/clang/test/CIR/CodeGenOpenMP/emit-device-functions.cpp
index 53a8e2b7aab71..014529d2104d3 100644
--- a/clang/test/CIR/CodeGenOpenMP/emit-device-functions.cpp
+++ b/clang/test/CIR/CodeGenOpenMP/emit-device-functions.cpp
@@ -33,7 +33,7 @@ void caller() {
 
 #pragma omp end declare target
 
-// CIR-DAG: cir.func {{.*}} @_Z12regular_funcv() {{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)
+// CIR-DAG: cir.func {{.*}} @_Z12regular_funcv() {{.*}}omp.declare_target = #omp.declaretarget<device_type = any, capture_clause = to
 // CIR-DAG: cir.func {{.*}} @_Z6callerv() {{.*}}omp.declare_target
 // CIR-DAG: cir.func {{.*}} @_ZN1SC2Ev({{.*}})
 // CIR-DAG: cir.func {{.*}} @_ZN1SC1Ev({{.*}})
diff --git a/clang/test/CIR/Transforms/omp-mark-declare-target.cir b/clang/test/CIR/Transforms/omp-mark-declare-target.cir
index a32fccc20f970..daa082683d03a 100644
--- a/clang/test/CIR/Transforms/omp-mark-declare-target.cir
+++ b/clang/test/CIR/Transforms/omp-mark-declare-target.cir
@@ -10,22 +10,22 @@ module {
   // A helper function with no declare_target attribute initially.
   // After the pass, it should be marked because @caller calls it.
   // CHECK-LABEL: cir.func private @helper
-  // CHECK-SAME: omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)
+  // CHECK-SAME: omp.declare_target = #omp.declaretarget<device_type = host, capture_clause = to
   cir.func private @helper() {
     cir.return
   }
 
   // Explicitly marked as declare_target; calls @helper.
   // CHECK-LABEL: cir.func @caller
-  // CHECK-SAME: omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>
-  cir.func @caller() attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>} {
+  // CHECK-SAME: omp.declare_target = #omp.declaretarget<device_type = host, capture_clause = to>
+  cir.func @caller() attributes {omp.declare_target = #omp.declaretarget<device_type = host, capture_clause = to>} {
     cir.call @helper() : () -> ()
     cir.return
   }
 
   // Called from within an omp.target region; should be marked as nohost.
   // CHECK-LABEL: cir.func private @device_helper
-  // CHECK-SAME: omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to)
+  // CHECK-SAME: omp.declare_target = #omp.declaretarget<device_type = nohost, capture_clause = to
   cir.func private @device_helper() {
     cir.return
   }
diff --git a/flang/docs/OpenMP-declare-target.md b/flang/docs/OpenMP-declare-target.md
index 3a7d001d15846..1e98068a2961b 100644
--- a/flang/docs/OpenMP-declare-target.md
+++ b/flang/docs/OpenMP-declare-target.md
@@ -93,8 +93,11 @@ operations to access the appropriate interface functions, e.g.:
 
 ```C++
 auto declareTargetGlobal =
-llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(Op.getOperation());
-declareTargetGlobal.isDeclareTarget();
+    llvm::cast<mlir::omp::DeclareTargetInterface>(op.getOperation());
+auto declareTargetAttr = declareTargetGlobal.getDeclareTarget();
+if (declareTargetAttr) {
+    auto deviceType = declareTargetAttr.getDeviceType();
+}
 ```
 
 ## Declare Target Fortran OpenMP Lowering
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index becb05b5af2c2..28b7458981d76 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -1764,10 +1764,12 @@ getImplicitMapTypeAndKind(fir::FirOpBuilder &firOpBuilder,
       }
     }
 
-    if (declareTargetOp && declareTargetOp.isDeclareTarget()) {
-      if (declareTargetOp.getDeclareTargetCaptureClause() ==
+    mlir::omp::DeclareTargetAttr declareTargetAttr =
+        declareTargetOp ? declareTargetOp.getDeclareTarget() : nullptr;
+    if (declareTargetAttr) {
+      if (declareTargetAttr.getCaptureClause() ==
               mlir::omp::DeclareTargetCaptureClause::link &&
-          declareTargetOp.getDeclareTargetDeviceType() !=
+          declareTargetAttr.getDeviceType() !=
               mlir::omp::DeclareTargetDeviceType::nohost) {
         mapFlag |= mlir::omp::ClauseMapFlags::to;
         mapFlag |= mlir::omp::ClauseMapFlags::from;
@@ -1847,8 +1849,9 @@ markDeclareTarget(mlir::Operation *op, lower::AbstractConverter &converter,
   // likely through implicit capture (usage in another declare target
   // function/subroutine). It should be marked as any if it has been assigned
   // both host and nohost, else we skip, as there is no change
-  if (declareTargetOp.isDeclareTarget()) {
-    if (declareTargetOp.getDeclareTargetDeviceType() != deviceType)
+  if (mlir::omp::DeclareTargetAttr declareTargetAttr =
+          declareTargetOp.getDeclareTarget()) {
+    if (declareTargetAttr.getDeviceType() != deviceType)
       declareTargetOp.setDeclareTarget(mlir::omp::DeclareTargetDeviceType::any,
                                        captureClause, automap,
                                        /*implicit=*/false);
diff --git a/flang/lib/Optimizer/OpenMP/AutomapToTargetData.cpp b/flang/lib/Optimizer/OpenMP/AutomapToTargetData.cpp
index bf269b5dd3ff2..0ec0c9193e969 100644
--- a/flang/lib/Optimizer/OpenMP/AutomapToTargetData.cpp
+++ b/flang/lib/Optimizer/OpenMP/AutomapToTargetData.cpp
@@ -97,11 +97,13 @@ class AutomapToTargetDataPass
     llvm::DenseSet<fir::GlobalOp> automapGlobals;
     module.walk([&](fir::GlobalOp globalOp) {
       if (auto iface =
-              dyn_cast<omp::DeclareTargetInterface>(globalOp.getOperation()))
-        if (iface.isDeclareTarget() && iface.getDeclareTargetAutomap() &&
-            iface.getDeclareTargetDeviceType() !=
+              dyn_cast<omp::DeclareTargetInterface>(globalOp.getOperation())) {
+        omp::DeclareTargetAttr declareTargetAttr = iface.getDeclareTarget();
+        if (declareTargetAttr && declareTargetAttr.getAutomap() &&
+            declareTargetAttr.getDeviceType() !=
                 omp::DeclareTargetDeviceType::host)
           automapGlobals.insert(globalOp);
+      }
     });
 
     auto addMapInfo = [&](auto globalOp, auto memOp) {
diff --git a/flang/lib/Optimizer/OpenMP/UnimplementedDeviceCheck.cpp b/flang/lib/Optimizer/OpenMP/UnimplementedDeviceCheck.cpp
index c393e2f90f88f..faf7274444104 100644
--- a/flang/lib/Optimizer/OpenMP/UnimplementedDeviceCheck.cpp
+++ b/flang/lib/Optimizer/OpenMP/UnimplementedDeviceCheck.cpp
@@ -37,9 +37,10 @@ static bool allUsesInHostCode(Operation *moduleOp, SymbolOpInterface symOp) {
 
       if (auto declareTargetOp =
               symUser->getParentOfType<omp::DeclareTargetInterface>()) {
-        if (declareTargetOp.isDeclareTarget() &&
-            declareTargetOp.getDeclareTargetDeviceType() !=
-                omp::DeclareTargetDeviceType::host)
+        omp::DeclareTargetAttr declareTargetAttr =
+            declareTargetOp.getDeclareTarget();
+        if (declareTargetAttr && declareTargetAttr.getDeviceType() !=
+                                     omp::DeclareTargetDeviceType::host)
           return false;
       }
     }
diff --git a/flang/test/Integration/OpenMP/declare-target-funcs.f90 b/flang/test/Integration/OpenMP/declare-target-funcs.f90
index 66010b9b0838f..6a4ac0538c06b 100644
--- a/flang/test/Integration/OpenMP/declare-target-funcs.f90
+++ b/flang/test/Integration/OpenMP/declare-target-funcs.f90
@@ -16,8 +16,8 @@
 
 ! CHECK-LABEL: IR Dump Before HostOpFilteringPass: omp-host-op-filter
 ! CHECK: llvm.func{{.*}}@__mlir_math_ipowi_i32
-! CHECK-SAME: attributes{{.*}}omp.declare_target{{.*}}device_type =
-! CHECK-NOT: (host)
+! CHECK-SAME: attributes{{.*}}omp.declare_target = #omp.declaretarget<
+! CHECK-NOT: device_type = host
 
 module m
 contains
diff --git a/flang/test/Integration/OpenMP/declare-target-named-main-interface.f90 b/flang/test/Integration/OpenMP/declare-target-named-main-interface.f90
index 7f85324fc6869..1fa1ad12ec87c 100644
--- a/flang/test/Integration/OpenMP/declare-target-named-main-interface.f90
+++ b/flang/test/Integration/OpenMP/declare-target-named-main-interface.f90
@@ -16,7 +16,7 @@
 
 ! CHECK-NOT: llvm.func @_QQmain{{.*}}device_type = any
 ! CHECK-NOT: llvm.func @_QQmain{{.*}}device_type = nohost
-! CHECK: llvm.func @_QPsub_a{{.*}}device_type = any, {{.*}}sym_visibility = "private"
+! CHECK: llvm.func @_QPsub_a{{.*}}#omp.declaretarget<device_type = any, capture_clause = to>, {{.*}}sym_visibility = "private"
 
 program named_main
   interface
diff --git a/flang/test/Lower/OpenMP/declare-target-multiple-entry.f90 b/flang/test/Lower/OpenMP/declare-target-multiple-entry.f90
index e983093cbacee..2c46e567d1b76 100644
--- a/flang/test/Lower/OpenMP/declare-target-multiple-entry.f90
+++ b/flang/test/Lower/OpenMP/declare-target-multiple-entry.f90
@@ -4,9 +4,9 @@
 ! Test that a bare '!$omp declare target' inside a multiple entry subprogram
 ! marks all entries as declare-target functions.
 
-! CHECK: func.func @_QPfirst_entry{{.*}}device_type = any
-! CHECK: func.func @_QPsecond_entry{{.*}}device_type = any
-! CHECK: func.func @_QPthird_entry{{.*}}device_type = any
+! CHECK: func.func @_QPfirst_entry{{.*}}omp.declare_target
+! CHECK: func.func @_QPsecond_entry{{.*}}omp.declare_target
+! CHECK: func.func @_QPthird_entry{{.*}}omp.declare_target
 
 subroutine first_entry()
   implicit none
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
index b80c2f6aba441..a7c865dc3b11c 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
@@ -43,8 +43,8 @@ def AtomicControlAttr : OpenMP_Attr<"AtomicControl", "atomic_control"> {
 
 def DeclareTargetAttr : OpenMP_Attr<"DeclareTarget", "declaretarget"> {
   let parameters =
-      (ins OptionalEnumAttrParameter<DeclareTargetDeviceTypeAttr>:$device_type,
-          OptionalEnumAttrParameter<DeclareTargetCaptureClauseAttr>:$capture_clause,
+      (ins "mlir::omp::DeclareTargetDeviceType":$device_type,
+          "mlir::omp::DeclareTargetCaptureClause":$capture_clause,
           DefaultValuedParameter<"bool", "false">:$automap,
           DefaultValuedParameter<"bool", "false">:$implicit);
 
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
index 9e1699e0482b5..a087439c87cb2 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
@@ -399,74 +399,28 @@ def DeclareTargetInterface : OpInterface<"DeclareTargetInterface"> {
            "bool":$automap, "bool":$implicit), [{}], [{
         $_op->setDiscardableAttr("omp.declare_target",
                   mlir::omp::DeclareTargetAttr::get(
-                      $_op->getContext(),
-                      mlir::omp::DeclareTargetDeviceTypeAttr::get(
-                          $_op->getContext(), deviceType),
-                      mlir::omp::DeclareTargetCaptureClauseAttr::get(
-                          $_op->getContext(), captureClause),
-                      automap, implicit));
+                      $_op->getContext(), deviceType, captureClause, automap,
+                      implicit));
       }]>,
-      InterfaceMethod<
-      /*description=*/[{
-        Checks if the declare target attribute has been applied and exists on the
-        current operation. Returns true if it exists on it, otherwise returns
-        false.
-      }],
-      /*retTy=*/"bool",
-      /*methodName=*/"isDeclareTarget",
-      (ins), [{}], [{
-        return $_op->hasDiscardableAttr("omp.declare_target");
-      }]>,
-      InterfaceMethod<
-      /*description=*/[{
-        Returns the DeclareTargetDeviceType segment of the DeclareTarget attribute if it
-        exists on the current operation. Otherwise it returns null.
-      }],
-      /*retTy=*/"mlir::omp::DeclareTargetDeviceType",
-      /*methodName=*/"getDeclareTargetDeviceType",
-      (ins), [{}], [{
-        if (mlir::Attribute dTar = $_op->getDiscardableAttr("omp.declare_target"))
-          if (auto dAttr = llvm::dyn_cast_or_null<mlir::omp::DeclareTargetAttr>(dTar))
-            return dAttr.getDeviceType().getValue();
-        return {};
-      }]>,
-      InterfaceMethod<
-      /*description=*/[{
-        Returns the DeclareTargetCaptureClause segment of the DeclareTarget attribute if it
-        exists on the current operation. Otherwise it returns null.
-      }],
-      /*retTy=*/"mlir::omp::DeclareTargetCaptureClause",
-      /*methodName=*/"getDeclareTargetCaptureClause",
-      (ins), [{}], [{
-        if (mlir::Attribute dTar = $_op->getDiscardableAttr("omp.declare_target"))
-          if (auto dAttr = llvm::dyn_cast_or_null<mlir::omp::DeclareTargetAttr>(dTar))
-            return dAttr.getCaptureClause().getValue();
-        return {};
-      }]>,
-      InterfaceMethod<
+    InterfaceMethod<
       /*description=*/[{
-        Return true if the DeclareTarget attribute has the AUTOMAP modifier.
+        Set the declare target attribute on the current operation.
       }],
-      /*retTy=*/"bool",
-      /*methodName=*/"getDeclareTargetAutomap",
-      (ins), [{}], [{
-        if (mlir::Attribute dTar = $_op->getDiscardableAttr("omp.declare_target"))
-          if (auto dAttr = llvm::dyn_cast_or_null<mlir::omp::DeclareTargetAttr>(dTar))
-            return dAttr.getAutomap();
-         return false;
+      /*retTy=*/"void",
+      /*methodName=*/"setDeclareTarget",
+      (ins "mlir::omp::DeclareTargetAttr":$attr), [{}], [{
+        $_op->setDiscardableAttr("omp.declare_target", attr);
       }]>,
-      InterfaceMethod<
+    InterfaceMethod<
       /*description=*/[{
-        Return true if the DeclareTarget attribute has been implicitly added.
+        Returns the declare target attribute if has been applied to the current
+        operation. Otherwise, it returns null.
       }],
-      /*retTy=*/"bool",
-      /*methodName=*/"isImplicitDeclareTarget",
+      /*retTy=*/"mlir::omp::DeclareTargetAttr",
+      /*methodName=*/"getDeclareTarget",
       (ins), [{}], [{
-        if (mlir::Attribute dTar =
-                $_op->getDiscardableAttr("omp.declare_target"))
-          if (auto dAttr = llvm::dyn_cast_or_null<mlir::omp::DeclareTargetAttr>(dTar))
-            return dAttr.getImplicit();
-         return false;
+        return llvm::cast_if_present<mlir::omp::DeclareTargetAttr>(
+            $_op->getDiscardableAttr("omp.declare_target"));
       }]>
   ];
 }
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 1f210ef60fe39..0213a80faedee 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -363,7 +363,7 @@ static LogicalResult verifyDeclareTargetAttr(Operation *op, Attribute attr) {
              << "omp.declare_target 'automap' is not valid on functions";
 
     // TODO: Disallow the `local` clause (OpenMP 6.0).
-    if (declareTargetAttr.getCaptureClause().getValue() ==
+    if (declareTargetAttr.getCaptureClause() ==
         mlir::omp::DeclareTargetCaptureClause::link)
       return op->emitOpError()
              << "omp.declare_target 'link' is not valid on functions";
diff --git a/mlir/lib/Dialect/OpenMP/Transforms/FunctionFiltering.cpp b/mlir/lib/Dialect/OpenMP/Transforms/FunctionFiltering.cpp
index 3b236dd69f425..626d54aa9de53 100644
--- a/mlir/lib/Dialect/OpenMP/Transforms/FunctionFiltering.cpp
+++ b/mlir/lib/Dialect/OpenMP/Transforms/FunctionFiltering.cpp
@@ -55,8 +55,10 @@ class FunctionFilteringPass
           omp::DeclareTargetDeviceType::host;
       auto declareTargetOp =
           dyn_cast<omp::DeclareTargetInterface>(funcOp.getOperation());
-      if (declareTargetOp && declareTargetOp.isDeclareTarget())
-        declareType = declareTargetOp.getDeclareTargetDeviceType();
+      omp::DeclareTargetAttr declareTargetAttr =
+          declareTargetOp ? declareTargetOp.getDeclareTarget() : nullptr;
+      if (declareTargetAttr)
+        declareType = declareTargetAttr.getDeviceType();
 
       // Only filter host functions from device modules because the host needs
       // to provide fallback implementations of device code.
@@ -98,7 +100,7 @@ class FunctionFilteringPass
       // marked as such to perform the second stage removal them from the device
       // module, where functions that contain target regions are deleted from
       // the generated LLVM IR.
-      if (declareTargetOp && !declareTargetOp.isDeclareTarget())
+      if (declareTargetOp && !declareTargetAttr)
         declareTargetOp.setDeclareTarget(omp::DeclareTargetDeviceType::host,
                                          omp::DeclareTargetCaptureClause::to,
                                          /*automap=*/false, /*implicit=*/true);
diff --git a/mlir/lib/Dialect/OpenMP/Transforms/HostOpFiltering.cpp b/mlir/lib/Dialect/OpenMP/Transforms/HostOpFiltering.cpp
index 9c61b2717af57..f7be1fdadfdb3 100644
--- a/mlir/lib/Dialect/OpenMP/Transforms/HostOpFiltering.cpp
+++ b/mlir/lib/Dialect/OpenMP/Transforms/HostOpFiltering.cpp
@@ -78,8 +78,10 @@ static void collectRewrite(Value value, llvm::SetVector<Value> &rewrites) {
 static std::optional<omp::DeclareTargetDeviceType>
 getDeclareTargetDevice(Operation &op) {
   auto declareTargetOp = dyn_cast<omp::DeclareTargetInterface>(op);
-  if (declareTargetOp && declareTargetOp.isDeclareTarget())
-    return declareTargetOp.getDeclareTargetDeviceType();
+  omp::DeclareTargetAttr declareTargetAttr =
+      declareTargetOp ? declareTargetOp.getDeclareTarget() : nullptr;
+  if (declareTargetAttr)
+    return declareTargetAttr.getDeviceType();
   return std::nullopt;
 }
 
diff --git a/mlir/lib/Dialect/OpenMP/Transforms/MarkDeclareTarget.cpp b/mlir/lib/Dialect/OpenMP/Transforms/MarkDeclareTarget.cpp
index d988752da84b9..e1395ebe4eb15 100644
--- a/mlir/lib/Dialect/OpenMP/Transforms/MarkDeclareTarget.cpp
+++ b/mlir/lib/Dialect/OpenMP/Transforms/MarkDeclareTarget.cpp
@@ -218,15 +218,17 @@ class MarkDeclareTargetPass
     for (auto funcOp : getOperation().getOps<FunctionOpInterface>()) {
       auto declareTargetOp =
           llvm::dyn_cast<omp::DeclareTargetInterface>(funcOp.getOperation());
+      omp::DeclareTargetAttr declareTargetAttr =
+          declareTargetOp ? declareTargetOp.getDeclareTarget() : nullptr;
 
-      if (!declareTargetOp || !declareTargetOp.isDeclareTarget())
+      if (!declareTargetAttr)
         continue;
 
       // Add to the worklist all called functions with the declare_target
       // information of this one, so it gets propagated.
       for (auto &callee : calls[funcOp.getName()])
         worklist.push_back(
-            {callee.getKey(), declareTargetOp.getDeclareTargetDeviceType()});
+            {callee.getKey(), declareTargetAttr.getDeviceType()});
     }
 
     // Add to the worklist all functions reached from target regions.
@@ -248,15 +250,17 @@ class MarkDeclareTargetPass
       // declare_target information to functions for which the user hasn't
       // specified an explicit behavior.
       auto declareTargetOp = dyn_cast<omp::DeclareTargetInterface>(*funcOp);
-      if (!declareTargetOp || (declareTargetOp.isDeclareTarget() &&
-                               !declareTargetOp.isImplicitDeclareTarget()))
+      omp::DeclareTargetAttr declareTargetAttr =
+          declareTargetOp ? declareTargetOp.getDeclareTarget() : nullptr;
+      if (!declareTargetOp ||
+          (declareTargetAttr && !declareTargetAttr.getImplicit()))
         continue;
 
       omp::DeclareTargetDeviceType changedDeviceType;
-      if (declareTargetOp.isDeclareTarget()) {
+      if (declareTargetAttr) {
         // Implicit declare_target update.
         omp::DeclareTargetDeviceType currentDeviceType =
-            declareTargetOp.getDeclareTargetDeviceType();
+            declareTargetAttr.getDeviceType();
 
         // Skip the update (and adding callees to the worklist) if the added
         // info doesn't change anything.
diff --git a/mlir/lib/Dialect/OpenMP/Utils/Utils.cpp b/mlir/lib/Dialect/OpenMP/Utils/Utils.cpp
index 537c5cea5b387..587210772896a 100644
--- a/mlir/lib/Dialect/OpenMP/Utils/Utils.cpp
+++ b/mlir/lib/Dialect/OpenMP/Utils/Utils.cpp
@@ -138,9 +138,10 @@ bool mlir::omp::opInSharedDeviceContext(Operation &op) {
       return false;
   } else {
     auto declTargetIface = op.getParentOfType<omp::DeclareTargetInterface>();
-    if (!declTargetIface || !declTargetIface.isDeclareTarget() ||
-        declTargetIface.getDeclareTargetDeviceType() ==
-            omp::DeclareTargetDeviceType::host)
+    omp::DeclareTargetAttr declTargetAttr =
+        declTargetIface ? declTargetIface.getDeclareTarget() : nullptr;
+    if (!declTargetAttr ||
+        declTargetAttr.getDeviceType() == omp::DeclareTargetDeviceType::host)
       return false;
   }
   return true;
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 1cbad3312235c..a114e74e62a77 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -6946,22 +6946,28 @@ getDeclareTargetRefPtrSuffix(LLVM::GlobalOp globalOp,
 static bool isDeclareTargetLink(Value value) {
   if (auto declareTargetGlobal =
           dyn_cast_if_present<omp::DeclareTargetInterface>(
-              getGlobalOpFromValue(value)))
-    if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
-        omp::DeclareTargetCaptureClause::link)
+              getGlobalOpFromValue(value))) {
+    omp::DeclareTargetAttr declareTargetAttr =
+        declareTargetGlobal.getDeclareTarget();
+    if (declareTargetAttr && declareTargetAttr.getCaptureClause() ==
+                                 omp::DeclareTargetCaptureClause::link)
       return true;
+  }
   return false;
 }
 
 static bool isDeclareTargetTo(Value value) {
   if (auto declareTargetGlobal =
           dyn_cast_if_present<omp::DeclareTargetInterface>(
-              getGlobalOpFromValue(value)))
-    if (declareTargetGlobal.getDeclareTargetCaptureClause() ==
-            omp::DeclareTargetCaptureClause::to ||
-        declareTargetGlobal.getDeclareTargetCaptureClause() ==
-            omp::DeclareTargetCaptureClause::enter)
+              getGlobalOpFromValue(value))) {
+    omp::DeclareTargetAttr declareTargetAttr =
+        declareTargetGlobal.getDeclareTarget();
+    if (declareTargetAttr && (declareTargetAttr.getCaptureClause() ==
+                                  omp::DeclareTargetCaptureClause::to ||
+                              declareTargetAttr.getCaptureClause() ==
+                                  omp::DeclareTargetCaptureClause::enter))
       return true;
+  }
   return false;
 }
 
@@ -9771,8 +9777,7 @@ convertDeclareTargetAttr(Operation *op, mlir::omp::DeclareTargetAttr attribute,
       if (!offloadMod.getIsTargetDevice())
         return success();
 
-      omp::DeclareTargetDeviceType declareType =
-          attribute.getDeviceType().getValue();
+      omp::DeclareTargetDeviceType declareType = attribute.getDeviceType();
 
       if (declareType == omp::DeclareTargetDeviceType::host) {
         llvm::Function *llvmFunc =
@@ -9815,10 +9820,9 @@ convertDeclareTargetAttr(Operation *op, mlir::omp::DeclareTargetAttr attribute,
       auto loc = op->getLoc()->findInstanceOf<FileLineColLoc>();
       llvm::StringRef mangledName = gOp.getSymName();
       mlir::omp::DeclareTargetCaptureClause captureClause =
-          attribute.getCaptureClause().getValue();
+          attribute.getCaptureClause();
       auto captureClauseKind = convertToCaptureClauseKind(captureClause);
-      auto deviceClause =
-          convertToDeviceClauseKind(attribute.getDeviceType().getValue());
+      auto deviceClause = convertToDeviceClauseKind(attribute.getDeviceType());
       llvm::StringRef entryMangledName = mangledName;
       llvm::Constant *entryAddr = llvm::cast<llvm::Constant>(gVal);
       std::function<llvm::GlobalValue::LinkageTypes()> variableLinkage;
@@ -9827,8 +9831,8 @@ convertDeclareTargetAttr(Operation *op, mlir::omp::DeclareTargetAttr attribute,
       bool isToOrEnter =
           captureClause == omp::DeclareTargetCaptureClause::to ||
           captureClause == omp::DeclareTargetCaptureClause::enter;
-      bool isHostOnly = attribute.getDeviceType().getValue() ==
-                        omp::DeclareTargetDeviceType::host;
+      bool isHostOnly =
+          attribute.getDeviceType() == omp::DeclareTargetDeviceType::host;
 
       // A to/enter declare-target variable needs a device-resident,
       // name-resolvable copy and a host offloading entry. A local-linkage
@@ -10116,11 +10120,13 @@ static bool isHostDeviceOp(Operation *op) {
   if (auto parentFn = op->getParentOfType<LLVM::LLVMFuncOp>()) {
     if (auto declareTargetIface =
             llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
-                parentFn.getOperation()))
-      if (declareTargetIface.isDeclareTarget() &&
-          declareTargetIface.getDeclareTargetDeviceType() !=
-              mlir::omp::DeclareTargetDeviceType::host)
+                parentFn.getOperation())) {
+      omp::DeclareTargetAttr declareTargetAttr =
+          declareTargetIface.getDeclareTarget();
+      if (declareTargetAttr && declareTargetAttr.getDeviceType() !=
+                                   mlir::omp::DeclareTargetDeviceType::host)
         return false;
+    }
 
     return true;
   }
diff --git a/mlir/test/Dialect/OpenMP/invalid-interface.mlir b/mlir/test/Dialect/OpenMP/invalid-interface.mlir
index ecbd17db54a41..567cf5b8c9707 100644
--- a/mlir/test/Dialect/OpenMP/invalid-interface.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid-interface.mlir
@@ -108,7 +108,7 @@ func.func @composable_conditional_combined(%x : i32) {
 // -----
 
 // 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
+%0 = arith.constant { omp.declare_target = #omp.declaretarget<device_type = any, capture_clause = enter> } 2 : i32
 
 // -----
 
@@ -118,17 +118,17 @@ func.func private @declare_target_attr_type() attributes { omp.declare_target =
 // -----
 
 // 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>}
+func.func private @declare_target_automap() attributes { omp.declare_target = #omp.declaretarget<device_type = any, capture_clause = enter, 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>}
+func.func private @declare_target_link() attributes { omp.declare_target = #omp.declaretarget<device_type = any, 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 {
+llvm.mlir.global @declare_target_implicit() {omp.declare_target = #omp.declaretarget<device_type = any, capture_clause = enter, implicit = true>} : i32 {
   %0 = llvm.mlir.constant(1 : i32) : i32
   llvm.return %0 : i32
 }



More information about the flang-commits mailing list