[Mlir-commits] [mlir] 7496177 - [openacc] Add dialect definition for acc declare

Razvan Lupusoru llvmlistbot at llvm.org
Tue Jul 18 08:11:28 PDT 2023


Author: Razvan Lupusoru
Date: 2023-07-18T08:11:06-07:00
New Revision: 7496177d983265974a0705d583e61e00d004fc5e

URL: https://github.com/llvm/llvm-project/commit/7496177d983265974a0705d583e61e00d004fc5e
DIFF: https://github.com/llvm/llvm-project/commit/7496177d983265974a0705d583e61e00d004fc5e.diff

LOG: [openacc] Add dialect definition for acc declare

A declare directive is used to specify the creation of a visible device
copy of a variable for the duration of the implicit data region as it
relates to the scope in which the variable is declared.

In order to support this, the following new operations were added:
1) `acc.global_ctor` and `acc.global_dtor`. These are used whenever the
declare directive applies to a global.
2) `acc.declare_enter` and `acc.declare_exit`. These operations are
modeled similarly to `acc.enter_data` and `acc.exit_data`. The reason
they are not modeled like `acc.data` is so that these operations can be
used both for globals and regions like functions.
3) `acc.declare_device_resident` and `acc.declare_link`. These
operations are modeled in a manner consistent with previously defined
data entry operation model.

The `acc.getdeviceptr` was generalized so that it can be used with
acc.declare_exit.

Reviewed By: clementval, vzakhari

Differential Revision: https://reviews.llvm.org/D155322

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
    mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
    mlir/test/Dialect/OpenACC/ops.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index a1af1cf7fea895..da00f307d1eba0 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -95,6 +95,8 @@ def OpenACC_UpdateSelf            : I64EnumAttrCase<"acc_update_self", 18>;
 def OpenACC_UpdateDevice          : I64EnumAttrCase<"acc_update_device", 19>;
 def OpenACC_UseDevice             : I64EnumAttrCase<"acc_use_device", 20>;
 def OpenACC_Reduction             : I64EnumAttrCase<"acc_reduction", 21>;
+def OpenACC_DeclareDeviceResident : I64EnumAttrCase<"acc_declare_device_resident", 22>;
+def OpenACC_DeclareLink           : I64EnumAttrCase<"acc_declare_link", 23>;
 
 def OpenACC_DataClauseEnum : I64EnumAttr<"DataClause",
     "data clauses supported by OpenACC",
@@ -105,7 +107,7 @@ def OpenACC_DataClauseEnum : I64EnumAttr<"DataClause",
      OpenACC_PrivateClause, OpenACC_FirstPrivateClause,
      OpenACC_IsDevicePtrClause, OpenACC_GetDevicePtrClause, OpenACC_UpdateHost,
      OpenACC_UpdateSelf, OpenACC_UpdateDevice, OpenACC_UseDevice,
-     OpenACC_Reduction,
+     OpenACC_Reduction, OpenACC_DeclareDeviceResident, OpenACC_DeclareLink,
     ]> {
   let cppNamespace = "::mlir::acc";
 }
@@ -181,7 +183,8 @@ def OpenACC_DataBoundsOp : OpenACC_Op<"bounds",
 //
 // The bounds are represented in rank order. Rank 0 (inner-most dimension) is
 // the first.
-class OpenACC_DataEntryOp<string mnemonic, string clause, list<Trait> traits = []> :
+class OpenACC_DataEntryOp<string mnemonic, string clause, string extraDescription,
+                          list<Trait> traits = []> :
     OpenACC_Op<mnemonic, !listconcat(traits,
         [AttrSizedOperandSegments])> {
   let arguments = (ins OpenACC_PointerLikeTypeInterface:$varPtr,
@@ -193,7 +196,8 @@ class OpenACC_DataEntryOp<string mnemonic, string clause, list<Trait> traits = [
                        OptionalAttr<StrAttr>:$name);
   let results = (outs OpenACC_PointerLikeTypeInterface:$accPtr);
 
-  let description = [{
+  let description = !strconcat(extraDescription, [{
+    Description of arguments:
     - `varPtr`: The address of variable to copy.
     - `varPtrPtr`: Specifies the address of varPtr - only used when the variable
     copied is a field in a struct. This is important for OpenACC due to implicit
@@ -211,7 +215,7 @@ class OpenACC_DataEntryOp<string mnemonic, string clause, list<Trait> traits = [
     - `implicit`: Whether this is an implicitly generated operation, such as copies
     done to satisfy "Variables with Implicitly Determined Data Attributes" in 2.6.2.
     - `name`: Holds the name of variable as specified in user clause (including bounds).
-  }];
+  }]);
 
   let assemblyFormat = [{
     `varPtr` `(` $varPtr `:` type($varPtr) `)`
@@ -228,7 +232,7 @@ class OpenACC_DataEntryOp<string mnemonic, string clause, list<Trait> traits = [
 // 2.5.13 private clause
 //===----------------------------------------------------------------------===//
 def OpenACC_PrivateOp : OpenACC_DataEntryOp<"private",
-    "mlir::acc::DataClause::acc_private"> {
+    "mlir::acc::DataClause::acc_private", ""> {
   let summary = "Represents private semantics for acc private clause.";
 }
 
@@ -236,7 +240,7 @@ def OpenACC_PrivateOp : OpenACC_DataEntryOp<"private",
 // 2.5.14 firstprivate clause
 //===----------------------------------------------------------------------===//
 def OpenACC_FirstprivateOp : OpenACC_DataEntryOp<"firstprivate",
-    "mlir::acc::DataClause::acc_firstprivate"> {
+    "mlir::acc::DataClause::acc_firstprivate", ""> {
   let summary = "Represents firstprivate semantic for the acc firstprivate "
                 "clause.";
 }
@@ -245,7 +249,7 @@ def OpenACC_FirstprivateOp : OpenACC_DataEntryOp<"firstprivate",
 // 2.5.15 reduction clause
 //===----------------------------------------------------------------------===//
 def OpenACC_ReductionOp : OpenACC_DataEntryOp<"reduction",
-    "mlir::acc::DataClause::acc_reduction"> {
+    "mlir::acc::DataClause::acc_reduction", ""> {
   let summary = "Represents reduction semantics for acc reduction clause.";
 }
 
@@ -253,7 +257,7 @@ def OpenACC_ReductionOp : OpenACC_DataEntryOp<"reduction",
 // 2.7.4 deviceptr clause
 //===----------------------------------------------------------------------===//
 def OpenACC_DevicePtrOp : OpenACC_DataEntryOp<"deviceptr",
-    "mlir::acc::DataClause::acc_deviceptr"> {
+    "mlir::acc::DataClause::acc_deviceptr", ""> {
   let summary = "Specifies that the variable pointer is a device pointer.";
 }
 
@@ -261,7 +265,7 @@ def OpenACC_DevicePtrOp : OpenACC_DataEntryOp<"deviceptr",
 // 2.7.5 present clause
 //===----------------------------------------------------------------------===//
 def OpenACC_PresentOp : OpenACC_DataEntryOp<"present",
-    "mlir::acc::DataClause::acc_present"> {
+    "mlir::acc::DataClause::acc_present", ""> {
   let summary = "Specifies that the variable is already present on device.";
 }
 
@@ -269,7 +273,7 @@ def OpenACC_PresentOp : OpenACC_DataEntryOp<"present",
 // 2.7.7 copyin clause
 //===----------------------------------------------------------------------===//
 def OpenACC_CopyinOp : OpenACC_DataEntryOp<"copyin",
-    "mlir::acc::DataClause::acc_copyin"> {
+    "mlir::acc::DataClause::acc_copyin", ""> {
   let summary = "Represents copyin semantics for acc data clauses like acc "
                 "copyin and acc copy.";
 
@@ -283,7 +287,7 @@ def OpenACC_CopyinOp : OpenACC_DataEntryOp<"copyin",
 // 2.7.9 create clause
 //===----------------------------------------------------------------------===//
 def OpenACC_CreateOp : OpenACC_DataEntryOp<"create",
-    "mlir::acc::DataClause::acc_create"> {
+    "mlir::acc::DataClause::acc_create", ""> {
   let summary = "Represents create semantics for acc data clauses like acc "
                 "create and acc copyout.";
 
@@ -297,7 +301,7 @@ def OpenACC_CreateOp : OpenACC_DataEntryOp<"create",
 // 2.7.10 no_create clause
 //===----------------------------------------------------------------------===//
 def OpenACC_NoCreateOp : OpenACC_DataEntryOp<"nocreate",
-    "mlir::acc::DataClause::acc_no_create"> {
+    "mlir::acc::DataClause::acc_no_create", ""> {
   let summary = "Represents acc no_create semantics.";
 }
 
@@ -305,7 +309,7 @@ def OpenACC_NoCreateOp : OpenACC_DataEntryOp<"nocreate",
 // 2.7.12 attach clause
 //===----------------------------------------------------------------------===//
 def OpenACC_AttachOp : OpenACC_DataEntryOp<"attach",
-    "mlir::acc::DataClause::acc_attach"> {
+    "mlir::acc::DataClause::acc_attach", ""> {
   let summary = "Represents acc attach semantics which updates a pointer in "
                 "device memory with the corresponding device address of the "
                 "pointee.";
@@ -315,20 +319,27 @@ def OpenACC_AttachOp : OpenACC_DataEntryOp<"attach",
 // 3.2.23 acc_deviceptr
 //===----------------------------------------------------------------------===//
 // This is needed to get device address without the additional semantics in
-// acc present.
+// acc present. Effectively, it can be used to get "accPtr" for any variable.
 // It is also useful for providing the device address for unstructured construct
 // exit_data since unlike structured constructs, there is no matching data entry
 // operation.
 def OpenACC_GetDevicePtrOp : OpenACC_DataEntryOp<"getdeviceptr",
-    "mlir::acc::DataClause::acc_getdeviceptr"> {
-  let summary = "Gets device address from host address if it exists on device.";
+    "mlir::acc::DataClause::acc_getdeviceptr", [{
+      This operation is used to get the `accPtr` for a variable. This is often
+      used in conjunction with data exit operations when the data entry
+      operation is not visible. This operation can have a `dataClause` argument
+      that is any of the valid `mlir::acc::DataClause` entries.
+      \
+    }]> {
+  let summary = "Gets device address if variable exists on device.";
+  let hasVerifier = 0;
 }
 
 //===----------------------------------------------------------------------===//
 // 2.14.4 device clause
 //===----------------------------------------------------------------------===//
 def OpenACC_UpdateDeviceOp : OpenACC_DataEntryOp<"update_device",
-    "mlir::acc::DataClause::acc_update_device"> {
+    "mlir::acc::DataClause::acc_update_device", ""> {
   let summary = "Represents acc update device semantics.";
 }
 
@@ -336,10 +347,26 @@ def OpenACC_UpdateDeviceOp : OpenACC_DataEntryOp<"update_device",
 // 2.8 use_device clause
 //===----------------------------------------------------------------------===//
 def OpenACC_UseDeviceOp : OpenACC_DataEntryOp<"use_device",
-    "mlir::acc::DataClause::acc_use_device"> {
+    "mlir::acc::DataClause::acc_use_device", ""> {
   let summary = "Represents acc use_device semantics.";
 }
 
+//===----------------------------------------------------------------------===//
+// 2.13.1 device_resident clause
+//===----------------------------------------------------------------------===//
+def OpenACC_DeclareDeviceResidentOp : OpenACC_DataEntryOp<"declare_device_resident",
+    "mlir::acc::DataClause::acc_declare_device_resident", ""> {
+  let summary = "Represents acc declare device_resident semantics.";
+}
+
+//===----------------------------------------------------------------------===//
+// 2.13.3 link clause
+//===----------------------------------------------------------------------===//
+def OpenACC_DeclareLinkOp : OpenACC_DataEntryOp<"declare_link",
+    "mlir::acc::DataClause::acc_declare_link", ""> {
+  let summary = "Represents acc declare link semantics.";
+}
+
 // Data exit operation does not refer to OpenACC spec terminology, but to
 // terminology used in this dialect. It refers to data operations that will appear
 // after data or compute region. It will be used as the base of acc dialect
@@ -1140,6 +1167,136 @@ def OpenACC_YieldOp : OpenACC_Op<"yield", [ReturnLike, Terminator,
   let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?";
 }
 
+//===----------------------------------------------------------------------===//
+// 2.13 Declare Directive
+//===----------------------------------------------------------------------===//
+
+def OpenACC_DeclareEnterOp : OpenACC_Op<"declare_enter", []> {
+  let summary = "declare directive - entry to implicit data region";
+
+  let description = [{
+    The "acc.declare_enter" operation represents the OpenACC declare directive
+    and captures the entry semantics to the implicit data region.
+    This operation is modeled similarly to "acc.enter_data".
+
+    Example showing `acc declare create(a)`:
+
+    ```mlir
+    %0 = acc.create varPtr(%a : !llvm.ptr<f32>) -> !llvm.ptr<f32>
+    acc.declare_enter dataOperands(%0 : !llvm.ptr<f32>)
+    ```
+  }];
+
+  let arguments = (ins Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands);
+
+  let assemblyFormat = [{
+    oilist(
+        `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`
+    )
+    attr-dict-with-keyword
+  }];
+
+  let hasVerifier = 1;
+}
+
+def OpenACC_DeclareExitOp : OpenACC_Op<"declare_exit", []> {
+  let summary = "declare directive - exit from implicit data region";
+
+  let description = [{
+    The "acc.declare_exit" operation represents the OpenACC declare directive
+    and captures the exit semantics from the implicit data region.
+    This operation is modeled similarly to "acc.exit_data".
+
+    Example showing `acc declare device_resident(a)`:
+
+    ```mlir
+    %0 = acc.getdeviceptr varPtr(%a : !llvm.ptr<f32>) -> !llvm.ptr<f32> {dataClause = 22}
+    acc.declare_exit dataOperands(%0 : !llvm.ptr<f32>)
+    acc.delete accPtr(%0 : !llvm.ptr<f32>) {dataClause = 22}
+    ```
+  }];
+
+  let arguments = (ins Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands);
+
+  let assemblyFormat = [{
+    oilist(
+        `dataOperands` `(` $dataClauseOperands `:` type($dataClauseOperands) `)`
+    )
+    attr-dict-with-keyword
+  }];
+
+  let hasVerifier = 1;
+}
+
+def OpenACC_GlobalConstructorOp : OpenACC_Op<"global_ctor",
+                                             [IsolatedFromAbove, Symbol]> {
+  let summary = "Used to hold construction operations associated with globals such as declare";
+
+  let description = [{
+    The "acc.global_ctor" operation is used to capture OpenACC actions to apply
+    on globals (such as `acc declare`) at the entry to the implicit data region.
+    This operation is isolated and intended to be used in a module.
+
+    Example showing `declare create` of global:
+
+    ```mlir
+    llvm.mlir.global external @globalvar() : i32 {
+      %0 = llvm.mlir.constant(0 : i32) : i32
+      llvm.return %0 : i32
+    }
+    acc.global_ctor @acc_constructor {
+      %0 = llvm.mlir.addressof @globalvar : !llvm.ptr<i32>
+      %1 = acc.create varPtr(%0 : !llvm.ptr<i32>) -> !llvm.ptr<i32>
+      acc.declare_enter dataOperands(%1 : !llvm.ptr<i32>)
+    }
+    ```
+  }];
+
+  let arguments = (ins SymbolNameAttr:$sym_name);
+  let regions = (region AnyRegion:$region);
+
+  let assemblyFormat = [{
+    $sym_name $region attr-dict-with-keyword
+  }];
+
+  let hasVerifier = 0;
+}
+
+def OpenACC_GlobalDestructorOp : OpenACC_Op<"global_dtor",
+                                            [IsolatedFromAbove, Symbol]> {
+  let summary = "Used to hold destruction operations associated with globals such as declare";
+
+  let description = [{
+    The "acc.global_dtor" operation is used to capture OpenACC actions to apply
+    on globals (such as `acc declare`) at the exit from the implicit data
+    region. This operation is isolated and intended to be used in a module.
+
+    Example showing delete associated with `declare create` of global:
+
+    ```mlir
+    llvm.mlir.global external @globalvar() : i32 {
+      %0 = llvm.mlir.constant(0 : i32) : i32
+      llvm.return %0 : i32
+    }
+    acc.global_dtor @acc_destructor {
+      %0 = llvm.mlir.addressof @globalvar : !llvm.ptr<i32>
+      %1 = acc.getdeviceptr varPtr(%0 : !llvm.ptr<i32>) -> !llvm.ptr<i32> {dataClause = 7}
+      acc.declare_exit dataOperands(%1 : !llvm.ptr<i32>)
+      acc.delete accPtr(%1 : !llvm.ptr<i32>) {dataClause = 7}
+    }
+    ```
+  }];
+
+  let arguments = (ins SymbolNameAttr:$sym_name);
+  let regions = (region AnyRegion:$region);
+
+  let assemblyFormat = [{
+    $sym_name $region attr-dict-with-keyword
+  }];
+
+  let hasVerifier = 0;
+}
+
 //===----------------------------------------------------------------------===//
 // 2.14.1. Init Directive
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index 9c6cffa8399dcb..f166b9df2c1de3 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -171,19 +171,24 @@ LogicalResult acc::AttachOp::verify() {
 }
 
 //===----------------------------------------------------------------------===//
-// GetDevicePtrOp
+// DeclareDeviceResidentOp
 //===----------------------------------------------------------------------===//
-LogicalResult acc::GetDevicePtrOp::verify() {
-  // This operation is also created for use in unstructured constructs
-  // when we need an "accPtr" to feed to exit operation. Thus we test
-  // for those cases as well:
-  if (getDataClause() != acc::DataClause::acc_getdeviceptr &&
-      getDataClause() != acc::DataClause::acc_copyout &&
-      getDataClause() != acc::DataClause::acc_delete &&
-      getDataClause() != acc::DataClause::acc_detach &&
-      getDataClause() != acc::DataClause::acc_update_host &&
-      getDataClause() != acc::DataClause::acc_update_self)
-    return emitError("getDevicePtr mismatch");
+
+LogicalResult acc::DeclareDeviceResidentOp::verify() {
+  if (getDataClause() != acc::DataClause::acc_declare_device_resident)
+    return emitError("data clause associated with device_resident operation "
+                     "must match its intent");
+  return success();
+}
+
+//===----------------------------------------------------------------------===//
+// DeclareLinkOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult acc::DeclareLinkOp::verify() {
+  if (getDataClause() != acc::DataClause::acc_declare_link)
+    return emitError(
+        "data clause associated with link operation must match its intent");
   return success();
 }
 
@@ -214,7 +219,12 @@ LogicalResult acc::DeleteOp::verify() {
   // Test for all clauses this operation can be decomposed from:
   if (getDataClause() != acc::DataClause::acc_delete &&
       getDataClause() != acc::DataClause::acc_create &&
-      getDataClause() != acc::DataClause::acc_create_zero)
+      getDataClause() != acc::DataClause::acc_create_zero &&
+      getDataClause() != acc::DataClause::acc_copyin &&
+      getDataClause() != acc::DataClause::acc_copyin_readonly &&
+      getDataClause() != acc::DataClause::acc_present &&
+      getDataClause() != acc::DataClause::acc_declare_device_resident &&
+      getDataClause() != acc::DataClause::acc_declare_link)
     return emitError(
         "data clause associated with delete operation must match its intent"
         " or specify original clause this operation was decomposed from");
@@ -965,6 +975,41 @@ void EnterDataOp::getCanonicalizationPatterns(RewritePatternSet &results,
   results.add<RemoveConstantIfCondition<EnterDataOp>>(context);
 }
 
+//===----------------------------------------------------------------------===//
+// DeclareEnterOp
+//===----------------------------------------------------------------------===//
+
+template <typename Op>
+static LogicalResult checkDeclareOperands(Op &op,
+                                          const mlir::ValueRange &operands) {
+  if (operands.empty())
+    return emitError(
+        op->getLoc(),
+        "at least one operand must appear on the declare operation");
+
+  for (mlir::Value operand : operands)
+    if (!mlir::isa<acc::CopyinOp, acc::CopyoutOp, acc::CreateOp,
+                   acc::DevicePtrOp, acc::GetDevicePtrOp, acc::PresentOp,
+                   acc::DeclareDeviceResidentOp, acc::DeclareLinkOp>(
+            operand.getDefiningOp()))
+      return op.emitError(
+          "expect valid declare data entry operation or acc.getdeviceptr "
+          "as defining op");
+  return success();
+}
+
+LogicalResult acc::DeclareEnterOp::verify() {
+  return checkDeclareOperands(*this, this->getDataClauseOperands());
+}
+
+//===----------------------------------------------------------------------===//
+// DeclareExitOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult acc::DeclareExitOp::verify() {
+  return checkDeclareOperands(*this, this->getDataClauseOperands());
+}
+
 //===----------------------------------------------------------------------===//
 // InitOp
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/test/Dialect/OpenACC/ops.mlir b/mlir/test/Dialect/OpenACC/ops.mlir
index fa2f8c9f90ca25..7a47456ce92357 100644
--- a/mlir/test/Dialect/OpenACC/ops.mlir
+++ b/mlir/test/Dialect/OpenACC/ops.mlir
@@ -1538,3 +1538,99 @@ func.func @acc_reduc_test(%a : i64) -> () {
 // CHECK-LABEL: func.func @acc_reduc_test(
 // CHECK-SAME:    %[[ARG0:.*]]: i64)
 // CHECK:         acc.serial reduction(@reduction_add_i64 -> %[[ARG0]] : i64)
+
+// -----
+
+func.func @testdeclareop(%a: memref<f32>, %b: memref<f32>, %c: memref<f32>) -> () {
+  %0 = acc.copyin varPtr(%a : memref<f32>) -> memref<f32>
+  // copyin(zero)
+  %1 = acc.copyin varPtr(%b : memref<f32>) -> memref<f32> {dataClause = 2}
+  // copy
+  %2 = acc.copyin varPtr(%c : memref<f32>) -> memref<f32> {dataClause = 3}
+  acc.declare_enter dataOperands(%0, %1, %2 : memref<f32>, memref<f32>, memref<f32>)
+
+  %3 = acc.create varPtr(%a : memref<f32>) -> memref<f32>
+  // copyout
+  %4 = acc.create varPtr(%b : memref<f32>) -> memref<f32> {dataClause = 4}
+  %5 = acc.present varPtr(%c : memref<f32>) -> memref<f32>
+  acc.declare_enter dataOperands(%3, %4, %5 : memref<f32>, memref<f32>, memref<f32>)
+
+  %6 = acc.deviceptr varPtr(%a : memref<f32>) -> memref<f32>
+  %7 = acc.declare_device_resident varPtr(%b : memref<f32>) -> memref<f32>
+  %8 = acc.declare_link varPtr(%c : memref<f32>) -> memref<f32>
+  acc.declare_enter dataOperands(%6, %7, %8 : memref<f32>, memref<f32>, memref<f32>)
+
+  acc.declare_exit dataOperands(%7, %8 : memref<f32>, memref<f32>)
+  acc.delete accPtr(%7 : memref<f32>) {dataClause = 22 }
+  acc.delete accPtr(%8 : memref<f32>) {dataClause = 23 }
+
+  acc.declare_exit dataOperands(%3, %4, %5 : memref<f32>, memref<f32>, memref<f32>)
+  acc.delete accPtr(%3 : memref<f32>) {dataClause = 7 }
+  acc.copyout accPtr(%4 : memref<f32>) to varPtr(%b : memref<f32>)
+  acc.delete accPtr(%5 : memref<f32>) {dataClause = 6 }
+
+  acc.declare_exit dataOperands(%0, %1, %2 : memref<f32>, memref<f32>, memref<f32>)
+  acc.delete accPtr(%0 : memref<f32>) {dataClause = 1 }
+  acc.delete accPtr(%1 : memref<f32>) {dataClause = 2 }
+  acc.copyout accPtr(%2 : memref<f32>) to varPtr(%c : memref<f32>) { dataClause = 3 }
+
+  return
+}
+
+// CHECK-LABEL: func.func @testdeclareop(
+// CHECK-SAME: %[[ARGA:.*]]: memref<f32>, %[[ARGB:.*]]: memref<f32>, %[[ARGC:.*]]: memref<f32>)
+// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[ARGA]] : memref<f32>) -> memref<f32>
+// CHECK-NEXT: %[[COPYINRO:.*]] = acc.copyin varPtr(%[[ARGB]] : memref<f32>) -> memref<f32> {dataClause = 2 : i64}
+// CHECK-NEXT: %[[COPY:.*]] = acc.copyin varPtr(%[[ARGC]] : memref<f32>) -> memref<f32> {dataClause = 3 : i64}
+// CHECK-NEXT: acc.declare_enter dataOperands(%[[COPYIN]], %[[COPYINRO]], %[[COPY]] : memref<f32>, memref<f32>, memref<f32>)
+// CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARGA]] : memref<f32>) -> memref<f32>
+// CHECK-NEXT: %[[COPYOUT:.*]] = acc.create varPtr(%[[ARGB]] : memref<f32>) -> memref<f32> {dataClause = 4 : i64}
+// CHECK-NEXT: %[[PRESENT:.*]] = acc.present varPtr(%[[ARGC]] : memref<f32>) -> memref<f32>
+// CHECK-NEXT: acc.declare_enter dataOperands(%[[CREATE]], %[[COPYOUT]], %[[PRESENT]] : memref<f32>, memref<f32>, memref<f32>)
+// CHECK: %[[DEVICEPTR:.*]] = acc.deviceptr varPtr(%[[ARGA]] : memref<f32>) -> memref<f32>
+// CHECK-NEXT: %[[DEVICERES:.*]] = acc.declare_device_resident varPtr(%[[ARGB]] : memref<f32>) -> memref<f32>
+// CHECK-NEXT: %[[LINK:.*]] = acc.declare_link varPtr(%[[ARGC]] : memref<f32>) -> memref<f32>
+// CHECK-NEXT: acc.declare_enter dataOperands(%[[DEVICEPTR]], %[[DEVICERES]], %[[LINK]] : memref<f32>, memref<f32>, memref<f32>)
+// CHECK: acc.declare_exit dataOperands(%[[DEVICERES]], %[[LINK]] : memref<f32>, memref<f32>)
+// CHECK-NEXT: acc.delete accPtr(%[[DEVICERES]] : memref<f32>) {dataClause = 22 : i64}
+// CHECK-NEXT: acc.delete accPtr(%[[LINK]] : memref<f32>) {dataClause = 23 : i64}
+// CHECK: acc.declare_exit dataOperands(%[[CREATE]], %[[COPYOUT]], %[[PRESENT]] : memref<f32>, memref<f32>, memref<f32>)
+// CHECK-NEXT: acc.delete accPtr(%[[CREATE]] : memref<f32>) {dataClause = 7 : i64}
+// CHECK-NEXT: acc.copyout accPtr(%[[COPYOUT]] : memref<f32>) to varPtr(%[[ARGB]] : memref<f32>)
+// CHECK-NEXT: acc.delete accPtr(%[[PRESENT]] : memref<f32>) {dataClause = 6 : i64}
+// CHECK: acc.declare_exit dataOperands(%[[COPYIN]], %[[COPYINRO]], %[[COPY]] : memref<f32>, memref<f32>, memref<f32>)
+// CHECK-NEXT: acc.delete accPtr(%[[COPYIN]] : memref<f32>) {dataClause = 1 : i64}
+// CHECK-NEXT: acc.delete accPtr(%[[COPYINRO]] : memref<f32>) {dataClause = 2 : i64}
+// CHECK-NEXT: acc.copyout accPtr(%[[COPY]] : memref<f32>) to varPtr(%[[ARGC]] : memref<f32>) {dataClause = 3 : i64}
+
+// -----
+
+llvm.mlir.global external @globalvar() : i32 {
+  %0 = llvm.mlir.constant(0 : i32) : i32
+  llvm.return %0 : i32
+}
+
+acc.global_ctor @acc_constructor {
+  %0 = llvm.mlir.addressof @globalvar : !llvm.ptr<i32>
+  %1 = acc.create varPtr(%0 : !llvm.ptr<i32>) -> !llvm.ptr<i32>
+  acc.declare_enter dataOperands(%1 : !llvm.ptr<i32>)
+  acc.terminator
+}
+
+acc.global_dtor @acc_destructor {
+  %0 = llvm.mlir.addressof @globalvar : !llvm.ptr<i32>
+  %1 = acc.getdeviceptr varPtr(%0 : !llvm.ptr<i32>) -> !llvm.ptr<i32> { dataClause = 7}
+  acc.declare_exit dataOperands(%1 : !llvm.ptr<i32>)
+  acc.delete accPtr(%1 : !llvm.ptr<i32>)
+  acc.terminator
+}
+
+// CHECK-LABEL: acc.global_ctor @acc_constructor
+// CHECK: %[[ADDR:.*]] = llvm.mlir.addressof @globalvar : !llvm.ptr<i32>
+// CHECK-NEXT: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !llvm.ptr<i32>) -> !llvm.ptr<i32>
+// CHECK-NEXT: acc.declare_enter dataOperands(%[[CREATE]] : !llvm.ptr<i32>)
+// CHECK: acc.global_dtor @acc_destructor
+// CHECK: %[[ADDR:.*]] = llvm.mlir.addressof @globalvar : !llvm.ptr<i32>
+// CHECK-NEXT: %[[DELETE:.*]] = acc.getdeviceptr varPtr(%[[ADDR]] : !llvm.ptr<i32>) -> !llvm.ptr<i32> {dataClause = 7 : i64}
+// CHECK-NEXT: acc.declare_exit dataOperands(%[[DELETE]] : !llvm.ptr<i32>)
+// CHECK-NEXT: acc.delete accPtr(%[[DELETE]] : !llvm.ptr<i32>)


        


More information about the Mlir-commits mailing list