[Mlir-commits] [mlir] [mlir][acc] Introduce MappableType interface (PR #122146)
Razvan Lupusoru
llvmlistbot at llvm.org
Wed Jan 8 12:41:57 PST 2025
https://github.com/razvanlupusoru updated https://github.com/llvm/llvm-project/pull/122146
>From 8a86c2629a420e2e78c3c6562a4b7cd2f5d28df2 Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Wed, 8 Jan 2025 09:33:45 -0800
Subject: [PATCH 1/2] [mlir][acc] Introduce MappableType interface
OpenACC data clause operations previously required that the variable
operand implemented PointerLikeType interface. This was a reasonable
constraint because the dialects currently mixed with `acc` do use
pointers to represent variables. However, this forces the "pointer"
abstraction to be exposed too early and some cases are not cleanly
representable through this approach (more specifically FIR's `fix.box`
abstraction).
Thus, relax this by allowing a variable to be a type which implements
either `PointerLikeType` interface or `MappableType` interface.
---
mlir/docs/Dialects/OpenACCDialect.md | 98 +++++-
mlir/include/mlir/Dialect/OpenACC/OpenACC.h | 44 ++-
.../mlir/Dialect/OpenACC/OpenACCOps.td | 284 +++++++++++-------
.../Dialect/OpenACC/OpenACCTypeInterfaces.td | 93 ++++++
mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp | 220 +++++++++++++-
.../Dialect/OpenACC/OpenACCOpsTest.cpp | 128 ++++++--
6 files changed, 696 insertions(+), 171 deletions(-)
diff --git a/mlir/docs/Dialects/OpenACCDialect.md b/mlir/docs/Dialects/OpenACCDialect.md
index 2f1bb194a167d4..39218a9676ff34 100755
--- a/mlir/docs/Dialects/OpenACCDialect.md
+++ b/mlir/docs/Dialects/OpenACCDialect.md
@@ -274,28 +274,96 @@ reference counters are zero, a delete action is performed.
### Types
-There are a few acc dialect type categories to describe:
-* type of acc data clause operation input `varPtr`
- - The type of `varPtr` must be pointer-like. This is done by
- attaching the `PointerLikeType` interface to the appropriate MLIR
- type. Although memory/storage concept is a lower level abstraction,
- it is useful because the OpenACC model distinguishes between host
- and device memory explicitly - and the mapping between the two is
- done through pointers. Thus, by explicitly requiring it in the
- dialect, the appropriate language frontend must create storage or
- use type that satisfies the mapping constraint.
+Since the `acc dialect` is meant to be used alongside other dialects which
+represent the source language, appropriate use of types and type interfaces is
+key to ensuring compatibility. This section describes those considerations.
+
+#### Data Clause Operation Types
+
+Data clause operations (eg. `acc.copyin`) rely on the following type
+considerations:
+* type of acc data clause operation input `var`
+ - The type of `var` must be one with `PointerLikeType` or `MappableType`
+ interfaces attached. The first, `PointerLikeType`, is useful because
+ the OpenACC memory model distinguishes between host and device memory
+ explicitly - and the mapping between the two is done through pointers. Thus,
+ by explicitly requiring it in the dialect, the appropriate language
+ frontend must create storage or use type that satisfies the mapping
+ constraint. The second possibility, `MappableType` was added because
+ memory/storage concept is a lower level abstraction and not all dialects
+ choose to use a pointer abstraction especially in the case where semantics
+ are more complex (such as `fir.box` which represents Fortran descriptors
+ and is defined in the `fir` dialect used from `flang`).
* type of result of acc data clause operations
- The type of the acc data clause operation is exactly the same as
- `varPtr`. This was done intentionally instead of introducing an
- `acc.ref/ptr` type so that IR compatibility and the dialect's
+ `var`. This was done intentionally instead of introducing specific `acc`
+ output types so that so that IR compatibility and the dialect's
existing strong type checking can be maintained. This is needed
since the `acc` dialect must live within another dialect whose type
- system is unknown to it. The only constraint is that the appropriate
- dialect type must use the `PointerLikeType` interface.
+ system is unknown to it.
+* variable type captured in `varType`
+ - When `var`'s type is `PointerLikeType`, the actual type of the target
+ may be lost. More specifically, dialects like `llvm` which use opaque
+ pointers, do not record the target variable's type. The use of this field
+ bridges this gap.
* type of decomposed clauses
- Decomposed clauses, such as `acc.bounds` and `acc.declare_enter`
produce types to allow their results to be used only in specific
- operations.
+ operations. These are synthetic types solely used for proper IR
+ construction.
+
+#### Pointer-Like Requirement
+
+The need to have pointer-type requirement in the acc dialect stems from
+a few different aspects:
+- Existing dialects like `hlfir`, `fir`, `cir`, `llvm` use a pointer
+representation for variables.
+- Reference counters (for data clauses) are described in terms of
+memory. In OpenACC spec 3.3 in section 2.6.7. It says: "A structured reference
+counter is incremented when entering each data or compute region that contain an
+explicit data clause or implicitly-determined data attributes for that section
+of memory". This implies addressability of memory.
+- Attach semantics (2.6.8 attachment counter) are specified using
+"address" terminology: "The attachment counter for a pointer is set to
+one whenever the pointer is attached to new target address, and
+incremented whenever an attach action for that pointer is performed for
+the same target address.
+
+#### Type Interfaces
+
+The `acc` dialect describes two different type interfaces which must be
+implemented and attached to the source dialect's types in order to allow use
+of data clause operations (eg. `acc.copyin`). They are as follows:
+* `PointerLikeType`
+ - The idea behind this interface is that variables end up being represented
+ as pointers in many dialects. More specifically, `fir`, `cir`, `llvm`
+ represent user declared local variables with some dialect specific form of
+ `alloca` operation which produce pointers. Globals, similarly, are referred by
+ their address through some form of `address_of` operation. Additionally, an
+ implementation for OpenACC runtime needs to distinguish between device and
+ host memory - also typically done by talking about pointers. So this type
+ interface requirement fits in naturally with OpenACC specification. Data
+ mapping operation semantics can often be simply described by a pointer and
+ size of the data it points to.
+* `MappableType`
+ - This interface was introduced because the `PointerLikeType` requirement
+ cannot represent cases when the source dialect does not use pointers. Also,
+ some cases, such as Fortran descriptor-backed arrays and Fortran optional
+ arguments, require decomposition into multiple steps. For example, in the
+ descriptor case, mapping of descriptor is needed, mapping of the data, and
+ implicit attach into device descriptor. In order to allow capturing all of
+ this complexity with a single data clause operation, the `MappableType`
+ interface was introduced. This is consistent with the dialect's goals
+ including being "able to regenerate the semantic equivalent of the user
+ pragmas".
+
+The intent is that a dialect's type system implements one of these two
+interfaces. And to be precise, a type should only implement one or the other
+(and not both) - since keeping them separate avoids ambiguity on what actually
+needs mapped. When `var` is `PointerLikeType`, the assumption is that the data
+pointed-to will be mapped. If the pointer-like type also implemented
+`MappableType` interface, it becomes ambiguous whether the data pointed to or
+the pointer itself is being mapped.
### Recipes
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACC.h b/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
index cda07d6a913649..748cb7f28fc8c4 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
@@ -25,6 +25,7 @@
#include "mlir/Dialect/OpenACC/OpenACCOpsInterfaces.h.inc"
#include "mlir/Dialect/OpenACC/OpenACCTypeInterfaces.h.inc"
#include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.h"
+#include "mlir/IR/Value.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"
#include "mlir/Interfaces/LoopLikeInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
@@ -83,16 +84,31 @@ namespace acc {
/// combined and the final mapping value would be 5 (4 | 1).
enum OpenACCExecMapping { NONE = 0, VECTOR = 1, WORKER = 2, GANG = 4 };
-/// Used to obtain the `varPtr` from a data clause operation.
+/// Used to obtain the `var` from a data clause operation.
/// Returns empty value if not a data clause operation or is a data exit
-/// operation with no `varPtr`.
-mlir::Value getVarPtr(mlir::Operation *accDataClauseOp);
-
-/// Used to obtain the `accPtr` from a data clause operation.
-/// When a data entry operation, it obtains its result `accPtr` value.
-/// If a data exit operation, it obtains its operand `accPtr` value.
+/// operation with no `var`.
+mlir::Value getVar(mlir::Operation *accDataClauseOp);
+
+/// Used to obtain the `var` from a data clause operation if it implements
+/// `PointerLikeType`.
+mlir::TypedValue<mlir::acc::PointerLikeType>
+getVarPtr(mlir::Operation *accDataClauseOp);
+
+/// Used to obtains the `varType` from a data clause operation which records
+/// the type of variable. When `var` is `PointerLikeType`, this returns
+/// the type of the pointer target.
+mlir::Type getVarType(mlir::Operation *accDataClauseOp);
+
+/// Used to obtain the `accVar` from a data clause operation.
+/// When a data entry operation, it obtains its result `accVar` value.
+/// If a data exit operation, it obtains its operand `accVar` value.
/// Returns empty value if not a data clause operation.
-mlir::Value getAccPtr(mlir::Operation *accDataClauseOp);
+mlir::Value getAccVar(mlir::Operation *accDataClauseOp);
+
+/// Used to obtain the `accVar` from a data clause operation if it implements
+/// `PointerLikeType`.
+mlir::TypedValue<mlir::acc::PointerLikeType>
+getAccPtr(mlir::Operation *accDataClauseOp);
/// Used to obtain the `varPtrPtr` from a data clause operation.
/// Returns empty value if not a data clause operation.
@@ -136,6 +152,18 @@ mlir::ValueRange getDataOperands(mlir::Operation *accOp);
/// Used to get a mutable range iterating over the data operands.
mlir::MutableOperandRange getMutableDataOperands(mlir::Operation *accOp);
+/// Used to check whether the provided `type` implements the `PointerLikeType`
+/// interface.
+inline bool isPointerLikeType(mlir::Type type) {
+ return mlir::isa<mlir::acc::PointerLikeType>(type);
+}
+
+/// Used to check whether the provided `type` implements the `MappableType`
+/// interface.
+inline bool isMappableType(mlir::Type type) {
+ return mlir::isa<mlir::acc::MappableType>(type);
+}
+
/// Used to obtain the attribute name for declare.
static constexpr StringLiteral getDeclareAttrName() {
return StringLiteral("acc.declare");
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index 3ac265ac687561..a47f70b168066e 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -70,7 +70,14 @@ def IntOrIndex : AnyTypeOf<[AnyInteger, Index]>;
// Simple alias to pointer-like interface to reduce verbosity.
def OpenACC_PointerLikeType : TypeAlias<OpenACC_PointerLikeTypeInterface,
- "pointer-like type">;
+ "pointer-like type">;
+def OpenACC_MappableType : TypeAlias<OpenACC_MappableTypeInterface,
+ "mappable type">;
+
+def OpenACC_AnyPointerOrMappableLike : TypeConstraint<Or<[OpenACC_PointerLikeType.predicate,
+ OpenACC_MappableType.predicate]>, "any pointer or mappable">;
+def OpenACC_AnyPointerOrMappableType : Type<OpenACC_AnyPointerOrMappableLike.predicate,
+ "any pointer or mappable">;
// Define the OpenACC data clauses. There are a few cases where a modifier
// is used, like create(zero), copyin(readonly), and copyout(zero). Since in
@@ -353,7 +360,8 @@ def OpenACC_DataBoundsOp : OpenACC_Op<"bounds",
build($_builder, $_state,
::mlir::acc::DataBoundsType::get($_builder.getContext()),
/*lowerbound=*/{}, /*upperbound=*/{}, extent,
- /*stride=*/{}, /*strideInBytes=*/nullptr, /*startIdx=*/{});
+ /*stride=*/{}, /*strideInBytes=*/$_builder.getBoolAttr(false),
+ /*startIdx=*/{});
}]
>,
OpBuilder<(ins "::mlir::Value":$lowerbound,
@@ -361,7 +369,8 @@ def OpenACC_DataBoundsOp : OpenACC_Op<"bounds",
build($_builder, $_state,
::mlir::acc::DataBoundsType::get($_builder.getContext()),
lowerbound, upperbound, /*extent=*/{},
- /*stride=*/{}, /*strideInBytes=*/nullptr, /*startIdx=*/{});
+ /*stride=*/{}, /*strideInBytes=*/$_builder.getBoolAttr(false),
+ /*startIdx=*/{});
}]
>
];
@@ -396,10 +405,15 @@ class OpenACC_DataEntryOp<string mnemonic, string clause, string extraDescriptio
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
- attach semantics on data clauses (2.6.4).
+ - `var`: The variable to copy. Must be either `MappableType` or
+ `PointerLikeType`.
+ - `varType`: The type of the variable that is being copied. When `var` is
+ a `MappableType`, this matches the type of `var`. When `var` is a
+ `PointerLikeType`, this type holds information about the target of the
+ pointer.
+ - `varPtrPtr`: Specifies the address of the address of `var` - only used
+ when the variable copied is a field in a struct. This is important for
+ OpenACC due to implicit attach semantics on data clauses (2.6.4).
- `bounds`: Used when copying just slice of array or array's bounds are not
encoded in type. They are in rank order where rank 0 is inner-most dimension.
- `asyncOperands` and `asyncOperandsDeviceType`:
@@ -456,42 +470,74 @@ class OpenACC_DataEntryOp<string mnemonic, string clause, string extraDescriptio
}
return nullptr;
}
+ mlir::TypedValue<mlir::acc::PointerLikeType> getVarPtr() {
+ return mlir::dyn_cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(getVar());
+ }
+ mlir::TypedValue<mlir::acc::PointerLikeType> getAccPtr() {
+ return mlir::dyn_cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(getAccVar());
+ }
}];
let assemblyFormat = [{
- `varPtr` `(` $varPtr `:` custom<VarPtrType>(type($varPtr), $varType)
+ custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)
oilist(
`varPtrPtr` `(` $varPtrPtr `:` type($varPtrPtr) `)`
| `bounds` `(` $bounds `)`
| `async` `(` custom<DeviceTypeOperands>($asyncOperands,
type($asyncOperands), $asyncOperandsDeviceType) `)`
- ) `->` type($accPtr) attr-dict
+ ) `->` type($accVar) attr-dict
}];
let hasVerifier = 1;
- let builders = [OpBuilder<(ins "::mlir::Value":$varPtr, "bool":$structured,
- "bool":$implicit,
- CArg<"::mlir::ValueRange", "{}">:$bounds),
- [{
+ let builders = [
+ OpBuilder<(ins "::mlir::TypedValue<::mlir::acc::PointerLikeType>":$varPtr,
+ "bool":$structured, "bool":$implicit,
+ CArg<"::mlir::ValueRange", "{}">:$bounds),
+ [{
build($_builder, $_state, varPtr.getType(), varPtr,
/*varType=*/::mlir::TypeAttr::get(
- ::mlir::cast<::mlir::acc::PointerLikeType>(
- varPtr.getType()).getElementType()),
+ varPtr.getType().getElementType()),
/*varPtrPtr=*/{}, bounds, /*asyncOperands=*/{},
/*asyncOperandsDeviceType=*/nullptr,
/*asyncOnly=*/nullptr, /*dataClause=*/nullptr,
/*structured=*/$_builder.getBoolAttr(structured),
/*implicit=*/$_builder.getBoolAttr(implicit), /*name=*/nullptr);
}]>,
- OpBuilder<(ins "::mlir::Value":$varPtr, "bool":$structured,
- "bool":$implicit, "const ::llvm::Twine &":$name,
- CArg<"::mlir::ValueRange", "{}">:$bounds),
- [{
+ OpBuilder<(ins "::mlir::TypedValue<::mlir::acc::PointerLikeType>":$varPtr,
+ "bool":$structured, "bool":$implicit,
+ "const ::llvm::Twine &":$name,
+ CArg<"::mlir::ValueRange", "{}">:$bounds),
+ [{
build($_builder, $_state, varPtr.getType(), varPtr,
/*varType=*/::mlir::TypeAttr::get(
- ::mlir::cast<::mlir::acc::PointerLikeType>(
- varPtr.getType()).getElementType()),
+ varPtr.getType().getElementType()),
+ /*varPtrPtr=*/{}, bounds, /*asyncOperands=*/{},
+ /*asyncOperandsDeviceType=*/nullptr,
+ /*asyncOnly=*/nullptr, /*dataClause=*/nullptr,
+ /*structured=*/$_builder.getBoolAttr(structured),
+ /*implicit=*/$_builder.getBoolAttr(implicit),
+ /*name=*/$_builder.getStringAttr(name));
+ }]>,
+ OpBuilder<(ins "::mlir::TypedValue<::mlir::acc::MappableType>":$var,
+ "bool":$structured, "bool":$implicit,
+ CArg<"::mlir::ValueRange", "{}">:$bounds),
+ [{
+ build($_builder, $_state, var.getType(), var,
+ /*varType=*/::mlir::TypeAttr::get(var.getType()),
+ /*varPtrPtr=*/{}, bounds, /*asyncOperands=*/{},
+ /*asyncOperandsDeviceType=*/nullptr,
+ /*asyncOnly=*/nullptr, /*dataClause=*/nullptr,
+ /*structured=*/$_builder.getBoolAttr(structured),
+ /*implicit=*/$_builder.getBoolAttr(implicit), /*name=*/nullptr);
+ }]>,
+ OpBuilder<(ins "::mlir::TypedValue<::mlir::acc::MappableType>":$var,
+ "bool":$structured, "bool":$implicit,
+ "const ::llvm::Twine &":$name,
+ CArg<"::mlir::ValueRange", "{}">:$bounds),
+ [{
+ build($_builder, $_state, var.getType(), var,
+ /*varType=*/::mlir::TypeAttr::get(var.getType()),
/*varPtrPtr=*/{}, bounds, /*asyncOperands=*/{},
/*asyncOperandsDeviceType=*/nullptr,
/*asyncOnly=*/nullptr, /*dataClause=*/nullptr,
@@ -506,10 +552,10 @@ class OpenACC_DataEntryOp<string mnemonic, string clause, string extraDescriptio
//===----------------------------------------------------------------------===//
def OpenACC_PrivateOp : OpenACC_DataEntryOp<"private",
"mlir::acc::DataClause::acc_private", "", [],
- (ins OpenACC_PointerLikeTypeInterface:$varPtr)> {
+ (ins OpenACC_AnyPointerOrMappableType:$var)> {
let summary = "Represents private semantics for acc private clause.";
- let results = (outs Arg<OpenACC_PointerLikeTypeInterface,
- "Address of device variable",[MemWrite]>:$accPtr);
+ let results = (outs Arg<OpenACC_AnyPointerOrMappableType,
+ "Accelerator mapped variable",[MemWrite]>:$accVar);
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -518,11 +564,11 @@ def OpenACC_PrivateOp : OpenACC_DataEntryOp<"private",
//===----------------------------------------------------------------------===//
def OpenACC_FirstprivateOp : OpenACC_DataEntryOp<"firstprivate",
"mlir::acc::DataClause::acc_firstprivate", "", [],
- (ins Arg<OpenACC_PointerLikeTypeInterface,"Address of variable",[MemRead]>:$varPtr)> {
+ (ins Arg<OpenACC_AnyPointerOrMappableType,"Host variable",[MemRead]>:$var)> {
let summary = "Represents firstprivate semantic for the acc firstprivate "
"clause.";
- let results = (outs Arg<OpenACC_PointerLikeTypeInterface,
- "Address of device variable",[MemWrite]>:$accPtr);
+ let results = (outs Arg<OpenACC_AnyPointerOrMappableType,
+ "Accelerator mapped variable",[MemWrite]>:$accVar);
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -531,10 +577,10 @@ def OpenACC_FirstprivateOp : OpenACC_DataEntryOp<"firstprivate",
//===----------------------------------------------------------------------===//
def OpenACC_ReductionOp : OpenACC_DataEntryOp<"reduction",
"mlir::acc::DataClause::acc_reduction", "", [],
- (ins Arg<OpenACC_PointerLikeTypeInterface,"Address of variable",[MemRead]>:$varPtr)> {
+ (ins Arg<OpenACC_AnyPointerOrMappableType,"Host variable",[MemRead]>:$var)> {
let summary = "Represents reduction semantics for acc reduction clause.";
- let results = (outs Arg<OpenACC_PointerLikeTypeInterface,
- "Address of device variable",[MemWrite]>:$accPtr);
+ let results = (outs Arg<OpenACC_AnyPointerOrMappableType,
+ "Accelerator mapped variable",[MemWrite]>:$accVar);
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -544,9 +590,9 @@ def OpenACC_ReductionOp : OpenACC_DataEntryOp<"reduction",
def OpenACC_DevicePtrOp : OpenACC_DataEntryOp<"deviceptr",
"mlir::acc::DataClause::acc_deviceptr", "",
[MemoryEffects<[MemRead<OpenACC_RuntimeCounters>]>],
- (ins OpenACC_PointerLikeTypeInterface:$varPtr)> {
+ (ins OpenACC_AnyPointerOrMappableType:$var)> {
let summary = "Specifies that the variable pointer is a device pointer.";
- let results = (outs OpenACC_PointerLikeTypeInterface:$accPtr);
+ let results = (outs OpenACC_AnyPointerOrMappableType:$accVar);
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -557,9 +603,9 @@ def OpenACC_PresentOp : OpenACC_DataEntryOp<"present",
"mlir::acc::DataClause::acc_present", "",
[MemoryEffects<[MemRead<OpenACC_RuntimeCounters>,
MemWrite<OpenACC_RuntimeCounters>]>],
- (ins OpenACC_PointerLikeTypeInterface:$varPtr)> {
+ (ins OpenACC_AnyPointerOrMappableType:$var)> {
let summary = "Specifies that the variable is already present on device.";
- let results = (outs OpenACC_PointerLikeTypeInterface:$accPtr);
+ let results = (outs OpenACC_AnyPointerOrMappableType:$accVar);
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -570,11 +616,11 @@ def OpenACC_CopyinOp : OpenACC_DataEntryOp<"copyin",
"mlir::acc::DataClause::acc_copyin", "",
[MemoryEffects<[MemRead<OpenACC_RuntimeCounters>,
MemWrite<OpenACC_RuntimeCounters>]>],
- (ins Arg<OpenACC_PointerLikeTypeInterface,"Address of variable",[MemRead]>:$varPtr)> {
+ (ins Arg<OpenACC_AnyPointerOrMappableType,"Host variable",[MemRead]>:$var)> {
let summary = "Represents copyin semantics for acc data clauses like acc "
"copyin and acc copy.";
- let results = (outs Arg<OpenACC_PointerLikeTypeInterface,
- "Address of device variable",[MemWrite]>:$accPtr);
+ let results = (outs Arg<OpenACC_AnyPointerOrMappableType,
+ "Accelerator mapped variable",[MemWrite]>:$accVar);
let extraClassDeclaration = extraClassDeclarationBase # [{
/// Check if this is a copyin with readonly modifier.
@@ -589,11 +635,11 @@ def OpenACC_CreateOp : OpenACC_DataEntryOp<"create",
"mlir::acc::DataClause::acc_create", "",
[MemoryEffects<[MemRead<OpenACC_RuntimeCounters>,
MemWrite<OpenACC_RuntimeCounters>]>],
- (ins OpenACC_PointerLikeTypeInterface:$varPtr)> {
+ (ins OpenACC_AnyPointerOrMappableType:$var)> {
let summary = "Represents create semantics for acc data clauses like acc "
"create and acc copyout.";
- let results = (outs Arg<OpenACC_PointerLikeTypeInterface,
- "Address of device variable",[MemWrite]>:$accPtr);
+ let results = (outs Arg<OpenACC_AnyPointerOrMappableType,
+ "Accelerator mapped variable",[MemWrite]>:$accVar);
let extraClassDeclaration = extraClassDeclarationBase # [{
/// Check if this is a create with zero modifier.
@@ -608,9 +654,9 @@ def OpenACC_NoCreateOp : OpenACC_DataEntryOp<"nocreate",
"mlir::acc::DataClause::acc_no_create", "",
[MemoryEffects<[MemRead<OpenACC_RuntimeCounters>,
MemWrite<OpenACC_RuntimeCounters>]>],
- (ins OpenACC_PointerLikeTypeInterface:$varPtr)> {
+ (ins OpenACC_AnyPointerOrMappableType:$var)> {
let summary = "Represents acc no_create semantics.";
- let results = (outs OpenACC_PointerLikeTypeInterface:$accPtr);
+ let results = (outs OpenACC_AnyPointerOrMappableType:$accVar);
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -621,11 +667,11 @@ def OpenACC_AttachOp : OpenACC_DataEntryOp<"attach",
"mlir::acc::DataClause::acc_attach", "",
[MemoryEffects<[MemRead<OpenACC_RuntimeCounters>,
MemWrite<OpenACC_RuntimeCounters>]>],
- (ins Arg<OpenACC_PointerLikeTypeInterface,"Address of variable",[MemRead]>:$varPtr)> {
+ (ins Arg<OpenACC_AnyPointerOrMappableType,"Host variable",[MemRead]>:$var)> {
let summary = "Represents acc attach semantics which updates a pointer in "
"device memory with the corresponding device address of the "
"pointee.";
- let results = (outs OpenACC_PointerLikeTypeInterface:$accPtr);
+ let results = (outs OpenACC_AnyPointerOrMappableType:$accVar);
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -645,9 +691,9 @@ def OpenACC_GetDevicePtrOp : OpenACC_DataEntryOp<"getdeviceptr",
that is any of the valid `mlir::acc::DataClause` entries.
\
}], [MemoryEffects<[MemRead<OpenACC_RuntimeCounters>]>],
- (ins OpenACC_PointerLikeTypeInterface:$varPtr)> {
+ (ins OpenACC_AnyPointerOrMappableType:$var)> {
let summary = "Gets device address if variable exists on device.";
- let results = (outs OpenACC_PointerLikeTypeInterface:$accPtr);
+ let results = (outs OpenACC_AnyPointerOrMappableType:$accVar);
let hasVerifier = 0;
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -657,10 +703,10 @@ def OpenACC_GetDevicePtrOp : OpenACC_DataEntryOp<"getdeviceptr",
//===----------------------------------------------------------------------===//
def OpenACC_UpdateDeviceOp : OpenACC_DataEntryOp<"update_device",
"mlir::acc::DataClause::acc_update_device", "", [],
- (ins Arg<OpenACC_PointerLikeTypeInterface,"Address of variable",[MemRead]>:$varPtr)> {
+ (ins Arg<OpenACC_AnyPointerOrMappableType,"Host variable",[MemRead]>:$var)> {
let summary = "Represents acc update device semantics.";
- let results = (outs Arg<OpenACC_PointerLikeTypeInterface,
- "Address of device variable",[MemWrite]>:$accPtr);
+ let results = (outs Arg<OpenACC_AnyPointerOrMappableType,
+ "Accelerator mapped variable",[MemWrite]>:$accVar);
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -670,9 +716,9 @@ def OpenACC_UpdateDeviceOp : OpenACC_DataEntryOp<"update_device",
def OpenACC_UseDeviceOp : OpenACC_DataEntryOp<"use_device",
"mlir::acc::DataClause::acc_use_device", "",
[MemoryEffects<[MemRead<OpenACC_RuntimeCounters>]>],
- (ins OpenACC_PointerLikeTypeInterface:$varPtr)> {
+ (ins OpenACC_AnyPointerOrMappableType:$var)> {
let summary = "Represents acc use_device semantics.";
- let results = (outs OpenACC_PointerLikeTypeInterface:$accPtr);
+ let results = (outs OpenACC_AnyPointerOrMappableType:$accVar);
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -682,9 +728,9 @@ def OpenACC_UseDeviceOp : OpenACC_DataEntryOp<"use_device",
def OpenACC_DeclareDeviceResidentOp : OpenACC_DataEntryOp<"declare_device_resident",
"mlir::acc::DataClause::acc_declare_device_resident", "",
[MemoryEffects<[MemWrite<OpenACC_RuntimeCounters>]>],
- (ins Arg<OpenACC_PointerLikeTypeInterface,"Address of variable",[MemRead]>:$varPtr)> {
+ (ins Arg<OpenACC_AnyPointerOrMappableType,"Host variable",[MemRead]>:$var)> {
let summary = "Represents acc declare device_resident semantics.";
- let results = (outs OpenACC_PointerLikeTypeInterface:$accPtr);
+ let results = (outs OpenACC_AnyPointerOrMappableType:$accVar);
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -694,9 +740,9 @@ def OpenACC_DeclareDeviceResidentOp : OpenACC_DataEntryOp<"declare_device_reside
def OpenACC_DeclareLinkOp : OpenACC_DataEntryOp<"declare_link",
"mlir::acc::DataClause::acc_declare_link", "",
[MemoryEffects<[MemWrite<OpenACC_RuntimeCounters>]>],
- (ins Arg<OpenACC_PointerLikeTypeInterface,"Address of variable",[MemRead]>:$varPtr)> {
+ (ins Arg<OpenACC_AnyPointerOrMappableType,"Host variable",[MemRead]>:$var)> {
let summary = "Represents acc declare link semantics.";
- let results = (outs OpenACC_PointerLikeTypeInterface:$accPtr);
+ let results = (outs OpenACC_AnyPointerOrMappableType:$accVar);
let extraClassDeclaration = extraClassDeclarationBase;
}
@@ -705,10 +751,10 @@ def OpenACC_DeclareLinkOp : OpenACC_DataEntryOp<"declare_link",
//===----------------------------------------------------------------------===//
def OpenACC_CacheOp : OpenACC_DataEntryOp<"cache",
"mlir::acc::DataClause::acc_cache", "", [NoMemoryEffect],
- (ins OpenACC_PointerLikeTypeInterface:$varPtr)> {
+ (ins OpenACC_AnyPointerOrMappableType:$var)> {
let summary = "Represents the cache directive that is associated with a "
"loop.";
- let results = (outs OpenACC_PointerLikeTypeInterface:$accPtr);
+ let results = (outs OpenACC_AnyPointerOrMappableType:$accVar);
let extraClassDeclaration = extraClassDeclarationBase # [{
/// Check if this is a cache with readonly modifier.
@@ -738,7 +784,7 @@ class OpenACC_DataExitOp<string mnemonic, string clause, string extraDescription
OptionalAttr<StrAttr>:$name));
let description = !strconcat(extraDescription, [{
- - `accPtr`: The acc address of variable. This is the link from the data-entry
+ - `accVar`: The acc variable. This is the link from the data-entry
operation used.
- `bounds`: Used when copying just slice of array or array's bounds are not
encoded in type. They are in rank order where rank 0 is inner-most dimension.
@@ -808,57 +854,67 @@ class OpenACC_DataExitOpWithVarPtr<string mnemonic, string clause>
[MemoryEffects<[MemRead<OpenACC_RuntimeCounters>,
MemWrite<OpenACC_RuntimeCounters>]>],
(ins Arg<OpenACC_PointerLikeTypeInterface,
- "Address of device variable", [MemRead]>:$accPtr,
+ "Accelerator mapped variable", [MemRead]>:$accVar,
Arg<OpenACC_PointerLikeTypeInterface,
- "Address of variable", [MemWrite]>:$varPtr,
+ "Host variable", [MemWrite]>:$var,
TypeAttr:$varType)> {
let assemblyFormat = [{
- `accPtr` `(` $accPtr `:` type($accPtr) `)`
+ custom<AccVar>($accVar, type($accVar))
(`bounds` `(` $bounds^ `)` )?
(`async` `(` custom<DeviceTypeOperands>($asyncOperands,
type($asyncOperands), $asyncOperandsDeviceType)^ `)`)?
- `to` `varPtr` `(` $varPtr `:` custom<VarPtrType>(type($varPtr), $varType)
+ `to` custom<Var>($var) `:` custom<VarPtrType>(type($var), $varType)
attr-dict
}];
- let builders = [OpBuilder<(ins "::mlir::Value":$accPtr,
- "::mlir::Value":$varPtr, "bool":$structured,
- "bool":$implicit,
- CArg<"::mlir::ValueRange", "{}">:$bounds),
- [{
+ let builders = [
+ OpBuilder<(ins "::mlir::TypedValue<::mlir::acc::PointerLikeType>":$accPtr,
+ "::mlir::TypedValue<::mlir::acc::PointerLikeType>":$varPtr,
+ "bool":$structured, "bool":$implicit,
+ CArg<"::mlir::ValueRange", "{}">:$bounds),
+ [{
build($_builder, $_state, accPtr, varPtr,
/*varType=*/::mlir::TypeAttr::get(
- ::mlir::cast<::mlir::acc::PointerLikeType>(
- varPtr.getType()).getElementType()),
+ varPtr.getType().getElementType()),
bounds, /*asyncOperands=*/{}, /*asyncOperandsDeviceType=*/nullptr,
/*asyncOnly=*/nullptr, /*dataClause=*/nullptr,
/*structured=*/$_builder.getBoolAttr(structured),
/*implicit=*/$_builder.getBoolAttr(implicit), /*name=*/nullptr);
}]>,
- OpBuilder<(ins "::mlir::Value":$accPtr,
- "::mlir::Value":$varPtr, "bool":$structured,
- "bool":$implicit, "const ::llvm::Twine &":$name,
- CArg<"::mlir::ValueRange", "{}">:$bounds),
- [{
+ OpBuilder<(ins "::mlir::TypedValue<::mlir::acc::PointerLikeType>":$accPtr,
+ "::mlir::TypedValue<::mlir::acc::PointerLikeType>":$varPtr,
+ "bool":$structured, "bool":$implicit,
+ "const ::llvm::Twine &":$name,
+ CArg<"::mlir::ValueRange", "{}">:$bounds),
+ [{
build($_builder, $_state, accPtr, varPtr,
/*varType=*/::mlir::TypeAttr::get(
- ::mlir::cast<::mlir::acc::PointerLikeType>(
- varPtr.getType()).getElementType()),
+ varPtr.getType().getElementType()),
bounds, /*asyncOperands=*/{}, /*asyncOperandsDeviceType=*/nullptr,
/*asyncOnly=*/nullptr, /*dataClause=*/nullptr,
/*structured=*/$_builder.getBoolAttr(structured),
/*implicit=*/$_builder.getBoolAttr(implicit),
/*name=*/$_builder.getStringAttr(name));
}]>];
+
+ code extraClassDeclarationDataExit = [{
+ mlir::TypedValue<mlir::acc::PointerLikeType> getVarPtr() {
+ return mlir::dyn_cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(getVar());
+ }
+ mlir::TypedValue<mlir::acc::PointerLikeType> getAccPtr() {
+ return mlir::dyn_cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(getAccVar());
+ }
+ }];
}
class OpenACC_DataExitOpNoVarPtr<string mnemonic, string clause> :
OpenACC_DataExitOp<mnemonic, clause, "",
[MemoryEffects<[MemRead<OpenACC_RuntimeCounters>,
MemWrite<OpenACC_RuntimeCounters>]>],
- (ins Arg<OpenACC_PointerLikeTypeInterface,"Address of device variable",[MemRead]>:$accPtr)> {
+ (ins Arg<OpenACC_PointerLikeTypeInterface,"Accelerator mapped variable",
+ [MemRead]>:$accVar)> {
let assemblyFormat = [{
- `accPtr` `(` $accPtr `:` type($accPtr) `)`
+ custom<AccVar>($accVar, type($accVar))
(`bounds` `(` $bounds^ `)` )?
(`async` `(` custom<DeviceTypeOperands>($asyncOperands,
type($asyncOperands), $asyncOperandsDeviceType)^ `)`)?
@@ -866,31 +922,35 @@ class OpenACC_DataExitOpNoVarPtr<string mnemonic, string clause> :
}];
let builders = [
- OpBuilder<(ins "::mlir::Value":$accPtr,
- "bool":$structured,
- "bool":$implicit,
- CArg<"::mlir::ValueRange", "{}">:$bounds), [{
+ OpBuilder<(ins "::mlir::TypedValue<::mlir::acc::PointerLikeType>":$accPtr,
+ "bool":$structured, "bool":$implicit,
+ CArg<"::mlir::ValueRange", "{}">:$bounds),
+ [{
build($_builder, $_state, accPtr,
bounds, /*asyncOperands=*/{}, /*asyncOperandsDeviceType=*/nullptr,
/*asyncOnly=*/nullptr, /*dataClause=*/nullptr,
/*structured=*/$_builder.getBoolAttr(structured),
/*implicit=*/$_builder.getBoolAttr(implicit), /*name=*/nullptr);
- }]
- >,
- OpBuilder<(ins "::mlir::Value":$accPtr,
- "bool":$structured,
- "bool":$implicit,
- "const ::llvm::Twine &":$name,
- CArg<"::mlir::ValueRange", "{}">:$bounds), [{
+ }]>,
+ OpBuilder<(ins "::mlir::TypedValue<::mlir::acc::PointerLikeType>":$accPtr,
+ "bool":$structured, "bool":$implicit,
+ "const ::llvm::Twine &":$name,
+ CArg<"::mlir::ValueRange", "{}">:$bounds),
+ [{
build($_builder, $_state, accPtr,
bounds, /*asyncOperands=*/{}, /*asyncOperandsDeviceType=*/nullptr,
/*asyncOnly=*/nullptr, /*dataClause=*/nullptr,
/*structured=*/$_builder.getBoolAttr(structured),
/*implicit=*/$_builder.getBoolAttr(implicit),
/*name=*/$_builder.getStringAttr(name));
- }]
- >
+ }]>
];
+
+ code extraClassDeclarationDataExit = [{
+ mlir::TypedValue<mlir::acc::PointerLikeType> getAccPtr() {
+ return mlir::dyn_cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(getAccVar());
+ }
+ }];
}
//===----------------------------------------------------------------------===//
@@ -900,7 +960,7 @@ def OpenACC_CopyoutOp : OpenACC_DataExitOpWithVarPtr<"copyout",
"mlir::acc::DataClause::acc_copyout"> {
let summary = "Represents acc copyout semantics - reverse of copyin.";
- let extraClassDeclaration = extraClassDeclarationBase # [{
+ let extraClassDeclaration = extraClassDeclarationBase # extraClassDeclarationDataExit # [{
/// Check if this is a copyout with zero modifier.
bool isCopyoutZero();
}];
@@ -912,7 +972,7 @@ def OpenACC_CopyoutOp : OpenACC_DataExitOpWithVarPtr<"copyout",
def OpenACC_DeleteOp : OpenACC_DataExitOpNoVarPtr<"delete",
"mlir::acc::DataClause::acc_delete"> {
let summary = "Represents acc delete semantics - reverse of create.";
- let extraClassDeclaration = extraClassDeclarationBase;
+ let extraClassDeclaration = extraClassDeclarationBase # extraClassDeclarationDataExit;
}
//===----------------------------------------------------------------------===//
@@ -921,7 +981,7 @@ def OpenACC_DeleteOp : OpenACC_DataExitOpNoVarPtr<"delete",
def OpenACC_DetachOp : OpenACC_DataExitOpNoVarPtr<"detach",
"mlir::acc::DataClause::acc_detach"> {
let summary = "Represents acc detach semantics - reverse of attach.";
- let extraClassDeclaration = extraClassDeclarationBase;
+ let extraClassDeclaration = extraClassDeclarationBase # extraClassDeclarationDataExit;
}
//===----------------------------------------------------------------------===//
@@ -930,7 +990,7 @@ def OpenACC_DetachOp : OpenACC_DataExitOpNoVarPtr<"detach",
def OpenACC_UpdateHostOp : OpenACC_DataExitOpWithVarPtr<"update_host",
"mlir::acc::DataClause::acc_update_host"> {
let summary = "Represents acc update host semantics.";
- let extraClassDeclaration = extraClassDeclarationBase # [{
+ let extraClassDeclaration = extraClassDeclarationBase # extraClassDeclarationDataExit # [{
/// Check if this is an acc update self.
bool isSelf() {
return getDataClause() == acc::DataClause::acc_update_self;
@@ -1193,11 +1253,11 @@ def OpenACC_ParallelOp : OpenACC_Op<"parallel",
UnitAttr:$selfAttr,
Variadic<AnyType>:$reductionOperands,
OptionalAttr<SymbolRefArrayAttr>:$reductionRecipes,
- Variadic<OpenACC_PointerLikeTypeInterface>:$privateOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$privateOperands,
OptionalAttr<SymbolRefArrayAttr>:$privatizations,
- Variadic<OpenACC_PointerLikeTypeInterface>:$firstprivateOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$firstprivateOperands,
OptionalAttr<SymbolRefArrayAttr>:$firstprivatizations,
- Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$dataClauseOperands,
OptionalAttr<DefaultValueAttr>:$defaultAttr,
UnitAttr:$combined);
@@ -1353,11 +1413,11 @@ def OpenACC_SerialOp : OpenACC_Op<"serial",
UnitAttr:$selfAttr,
Variadic<AnyType>:$reductionOperands,
OptionalAttr<SymbolRefArrayAttr>:$reductionRecipes,
- Variadic<OpenACC_PointerLikeTypeInterface>:$privateOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$privateOperands,
OptionalAttr<SymbolRefArrayAttr>:$privatizations,
- Variadic<OpenACC_PointerLikeTypeInterface>:$firstprivateOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$firstprivateOperands,
OptionalAttr<SymbolRefArrayAttr>:$firstprivatizations,
- Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$dataClauseOperands,
OptionalAttr<DefaultValueAttr>:$defaultAttr,
UnitAttr:$combined);
@@ -1482,7 +1542,7 @@ def OpenACC_KernelsOp : OpenACC_Op<"kernels",
Optional<I1>:$ifCond,
Optional<I1>:$selfCond,
UnitAttr:$selfAttr,
- Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$dataClauseOperands,
OptionalAttr<DefaultValueAttr>:$defaultAttr,
UnitAttr:$combined);
@@ -1614,7 +1674,7 @@ def OpenACC_DataOp : OpenACC_Op<"data",
OptionalAttr<DeviceTypeArrayAttr>:$waitOperandsDeviceType,
OptionalAttr<BoolArrayAttr>:$hasWaitDevnum,
OptionalAttr<DeviceTypeArrayAttr>:$waitOnly,
- Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$dataClauseOperands,
OptionalAttr<DefaultValueAttr>:$defaultAttr);
let regions = (region AnyRegion:$region);
@@ -1709,7 +1769,7 @@ def OpenACC_EnterDataOp : OpenACC_Op<"enter_data",
Optional<IntOrIndex>:$waitDevnum,
Variadic<IntOrIndex>:$waitOperands,
UnitAttr:$wait,
- Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands);
+ Variadic<OpenACC_AnyPointerOrMappableType>:$dataClauseOperands);
let extraClassDeclaration = [{
/// The number of data operands.
@@ -1760,7 +1820,7 @@ def OpenACC_ExitDataOp : OpenACC_Op<"exit_data",
Optional<IntOrIndex>:$waitDevnum,
Variadic<IntOrIndex>:$waitOperands,
UnitAttr:$wait,
- Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$dataClauseOperands,
UnitAttr:$finalize);
let extraClassDeclaration = [{
@@ -1810,7 +1870,7 @@ def OpenACC_HostDataOp : OpenACC_Op<"host_data",
}];
let arguments = (ins Optional<I1>:$ifCond,
- Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$dataClauseOperands,
UnitAttr:$ifPresent);
let regions = (region AnyRegion:$region);
@@ -1887,8 +1947,8 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
Variadic<IntOrIndex>:$tileOperands,
OptionalAttr<DenseI32ArrayAttr>:$tileOperandsSegments,
OptionalAttr<DeviceTypeArrayAttr>:$tileOperandsDeviceType,
- Variadic<OpenACC_PointerLikeTypeInterface>:$cacheOperands,
- Variadic<OpenACC_PointerLikeTypeInterface>:$privateOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$cacheOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$privateOperands,
OptionalAttr<SymbolRefArrayAttr>:$privatizations,
Variadic<AnyType>:$reductionOperands,
OptionalAttr<SymbolRefArrayAttr>:$reductionRecipes,
@@ -2201,7 +2261,7 @@ def OpenACC_DeclareEnterOp : OpenACC_Op<"declare_enter",
```
}];
- let arguments = (ins Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands);
+ let arguments = (ins Variadic<OpenACC_AnyPointerOrMappableType>:$dataClauseOperands);
let results = (outs OpenACC_DeclareTokenType:$token);
let assemblyFormat = [{
@@ -2236,7 +2296,7 @@ def OpenACC_DeclareExitOp : OpenACC_Op<"declare_exit",
let arguments = (ins
Optional<OpenACC_DeclareTokenType>:$token,
- Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands);
+ Variadic<OpenACC_AnyPointerOrMappableType>:$dataClauseOperands);
let assemblyFormat = [{
oilist(
@@ -2338,7 +2398,7 @@ def OpenACC_DeclareOp : OpenACC_Op<"declare",
}];
let arguments = (ins
- Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands);
+ Variadic<OpenACC_AnyPointerOrMappableType>:$dataClauseOperands);
let regions = (region AnyRegion:$region);
@@ -2589,7 +2649,7 @@ def OpenACC_UpdateOp : OpenACC_Op<"update",
OptionalAttr<DeviceTypeArrayAttr>:$waitOperandsDeviceType,
OptionalAttr<BoolArrayAttr>:$hasWaitDevnum,
OptionalAttr<DeviceTypeArrayAttr>:$waitOnly,
- Variadic<OpenACC_PointerLikeTypeInterface>:$dataClauseOperands,
+ Variadic<OpenACC_AnyPointerOrMappableType>:$dataClauseOperands,
UnitAttr:$ifPresent);
let extraClassDeclaration = [{
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
index 0a3edd5637704e..bec46be89f0585 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
@@ -31,4 +31,97 @@ def OpenACC_PointerLikeTypeInterface : TypeInterface<"PointerLikeType"> {
];
}
+def OpenACC_MappableTypeInterface : TypeInterface<"MappableType"> {
+ let cppNamespace = "::mlir::acc";
+
+ let description = [{
+ An interface to capture type-based semantics for mapping in a manner that
+ makes it convertible to size-based semantics.
+ }];
+
+ let methods = [
+ InterfaceMethod<
+ /*description=*/[{
+ Returns the pointer to the `var` if recoverable (such as in cases
+ where the current operation is a load from a memory slot).
+ }],
+ /*retTy=*/"::mlir::TypedValue<::mlir::acc::PointerLikeType>",
+ /*methodName=*/"getVarPtr",
+ /*args=*/(ins "::mlir::Value":$var),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/[{
+ if (auto ptr = mlir::dyn_cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(
+ var))
+ return ptr;
+ return {};
+ }]
+ >,
+ InterfaceMethod<
+ /*description=*/[{
+ Returns the size in bytes when computable. If this is an array-like
+ type, avoiding passing `accBounds` ensures a computation of the size
+ of whole type.
+ }],
+ /*retTy=*/"::std::optional<::llvm::TypeSize>",
+ /*methodName=*/"getSizeInBytes",
+ /*args=*/(ins "::mlir::Value":$var,
+ "::mlir::ValueRange":$accBounds,
+ "const ::mlir::DataLayout &":$dataLayout),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/[{
+ // Bounds operations are typically created for array types. In the
+ // generic implementation, it is not straightforward to distinguish
+ // between array types and ensure the size and offset take into account
+ // just the slice requested. Thus return not-computable for now.
+ if (!accBounds.empty())
+ return {};
+ return {dataLayout.getTypeSize($_type)};
+ }]
+ >,
+ InterfaceMethod<
+ /*description=*/[{
+ Returns the offset in bytes when computable.
+ }],
+ /*retTy=*/"::std::optional<::int64_t>",
+ /*methodName=*/"getOffsetInBytes",
+ /*args=*/(ins "::mlir::Value":$var,
+ "::mlir::ValueRange":$accBounds,
+ "const ::mlir::DataLayout &":$dataLayout),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/[{
+ // Bounds operations are typically created for array types. In the
+ // generic implementation, it is not straightforward to distinguish
+ // between array types and ensure the size and offset take into account
+ // just the slice requested. Thus return not-computable for now.
+ if (!accBounds.empty())
+ return {};
+
+ // If the type size is computable, it means it is trivial. Assume
+ // offset of 0.
+ if (::mlir::cast<::mlir::acc::MappableType>($_type).getSizeInBytes(
+ var, accBounds, dataLayout).has_value()) {
+ return {0};
+ }
+
+ return {};
+ }]
+ >,
+ InterfaceMethod<
+ /*description=*/[{
+ Returns explicit `acc.bounds` operations that envelop the whole
+ data structure. These operations are inserted using the provided builder
+ at the location set before calling this API.
+ }],
+ /*retTy=*/"::llvm::SmallVector<::mlir::Value>",
+ /*methodName=*/"generateAccBounds",
+ /*args=*/(ins "::mlir::Value":$var,
+ "::mlir::OpBuilder &":$builder),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/[{
+ return {};
+ }]
+ >,
+ ];
+}
+
#endif // OPENACC_TYPE_INTERFACES
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index d490376db0e7fc..735dd4fd7b8bba 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -16,6 +16,7 @@
#include "mlir/IR/DialectImplementation.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/OpImplementation.h"
+#include "mlir/Support/LLVM.h"
#include "mlir/Transforms/DialectConversion.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/TypeSwitch.h"
@@ -192,6 +193,97 @@ static LogicalResult checkWaitAndAsyncConflict(Op op) {
return success();
}
+template <typename Op>
+static LogicalResult checkVarAndVarType(Op op) {
+ if (!op.getVar())
+ return op.emitError("must have var operand");
+
+ if (mlir::isa<mlir::acc::PointerLikeType>(op.getVar().getType()) &&
+ mlir::isa<mlir::acc::MappableType>(op.getVar().getType())) {
+ // TODO: If a type implements both interfaces (mappable and pointer-like),
+ // it is unclear which semantics to apply without additional info which
+ // would need captured in the data operation. For now restrict this case
+ // unless a compelling reason to support disambiguating between the two.
+ return op.emitError("var must be mappable or pointer-like (not both)");
+ }
+
+ if (!mlir::isa<mlir::acc::PointerLikeType>(op.getVar().getType()) &&
+ !mlir::isa<mlir::acc::MappableType>(op.getVar().getType()))
+ return op.emitError("var must be mappable or pointer-like");
+
+ if (mlir::isa<mlir::acc::MappableType>(op.getVar().getType()) &&
+ op.getVarType() != op.getVar().getType())
+ return op.emitError("varType must match when var is mappable");
+
+ return success();
+}
+
+template <typename Op>
+static LogicalResult checkVarAndAccVar(Op op) {
+ if (op.getVar().getType() != op.getAccVar().getType())
+ return op.emitError("input and output types must match");
+
+ return success();
+}
+
+static ParseResult parseVar(mlir::OpAsmParser &parser,
+ OpAsmParser::UnresolvedOperand &var) {
+ // Either `var` or `varPtr` keyword is required.
+ if (failed(parser.parseOptionalKeyword("varPtr"))) {
+ if (failed(parser.parseKeyword("var")))
+ return failure();
+ }
+ if (failed(parser.parseLParen()))
+ return failure();
+ if (failed(parser.parseOperand(var)))
+ return failure();
+
+ return success();
+}
+
+static void printVar(mlir::OpAsmPrinter &p, mlir::Operation *op,
+ mlir::Value var) {
+ if (mlir::isa<mlir::acc::PointerLikeType>(var.getType()))
+ p << "varPtr(";
+ else
+ p << "var(";
+ p.printOperand(var);
+}
+
+static ParseResult parseAccVar(mlir::OpAsmParser &parser,
+ OpAsmParser::UnresolvedOperand &var,
+ mlir::Type &accVarType) {
+ // Either `accVar` or `accPtr` keyword is required.
+ if (failed(parser.parseOptionalKeyword("accPtr"))) {
+ if (failed(parser.parseKeyword("accVar")))
+ return failure();
+ }
+ if (failed(parser.parseLParen()))
+ return failure();
+ if (failed(parser.parseOperand(var)))
+ return failure();
+ if (failed(parser.parseColon()))
+ return failure();
+ if (failed(parser.parseType(accVarType)))
+ return failure();
+ if (failed(parser.parseRParen()))
+ return failure();
+
+ return success();
+}
+
+static void printAccVar(mlir::OpAsmPrinter &p, mlir::Operation *op,
+ mlir::Value accVar, mlir::Type accVarType) {
+ if (mlir::isa<mlir::acc::PointerLikeType>(accVar.getType()))
+ p << "accPtr(";
+ else
+ p << "accVar(";
+ p.printOperand(accVar);
+ p << " : ";
+ p.printType(accVarType);
+ p << ")";
+}
+
static ParseResult parseVarPtrType(mlir::OpAsmParser &parser,
mlir::Type &varPtrType,
mlir::TypeAttr &varTypeAttr) {
@@ -211,8 +303,11 @@ static ParseResult parseVarPtrType(mlir::OpAsmParser &parser,
return failure();
} else {
// Set `varType` from the element type of the type of `varPtr`.
- varTypeAttr = mlir::TypeAttr::get(
- mlir::cast<mlir::acc::PointerLikeType>(varPtrType).getElementType());
+ if (mlir::isa<mlir::acc::PointerLikeType>(varPtrType))
+ varTypeAttr = mlir::TypeAttr::get(
+ mlir::cast<mlir::acc::PointerLikeType>(varPtrType).getElementType());
+ else
+ varTypeAttr = mlir::TypeAttr::get(varPtrType);
}
return success();
@@ -226,8 +321,11 @@ static void printVarPtrType(mlir::OpAsmPrinter &p, mlir::Operation *op,
// Print the `varType` only if it differs from the element type of
// `varPtr`'s type.
mlir::Type varType = varTypeAttr.getValue();
- if (mlir::cast<mlir::acc::PointerLikeType>(varPtrType).getElementType() !=
- varType) {
+ mlir::Type typeToCheckAgainst =
+ mlir::isa<mlir::acc::PointerLikeType>(varPtrType)
+ ? mlir::cast<mlir::acc::PointerLikeType>(varPtrType).getElementType()
+ : varPtrType;
+ if (typeToCheckAgainst != varType) {
p << " varType(";
p.printType(varType);
p << ")";
@@ -252,6 +350,8 @@ LogicalResult acc::PrivateOp::verify() {
if (getDataClause() != acc::DataClause::acc_private)
return emitError(
"data clause associated with private operation must match its intent");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
return success();
}
@@ -262,6 +362,8 @@ LogicalResult acc::FirstprivateOp::verify() {
if (getDataClause() != acc::DataClause::acc_firstprivate)
return emitError("data clause associated with firstprivate operation must "
"match its intent");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
return success();
}
@@ -272,6 +374,8 @@ LogicalResult acc::ReductionOp::verify() {
if (getDataClause() != acc::DataClause::acc_reduction)
return emitError("data clause associated with reduction operation must "
"match its intent");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
return success();
}
@@ -282,6 +386,10 @@ LogicalResult acc::DevicePtrOp::verify() {
if (getDataClause() != acc::DataClause::acc_deviceptr)
return emitError("data clause associated with deviceptr operation must "
"match its intent");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -292,6 +400,10 @@ LogicalResult acc::PresentOp::verify() {
if (getDataClause() != acc::DataClause::acc_present)
return emitError(
"data clause associated with present operation must match its intent");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -307,6 +419,10 @@ LogicalResult acc::CopyinOp::verify() {
return emitError(
"data clause associated with copyin operation must match its intent"
" or specify original clause this operation was decomposed from");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -326,6 +442,10 @@ LogicalResult acc::CreateOp::verify() {
return emitError(
"data clause associated with create operation must match its intent"
" or specify original clause this operation was decomposed from");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -342,6 +462,10 @@ LogicalResult acc::NoCreateOp::verify() {
if (getDataClause() != acc::DataClause::acc_no_create)
return emitError("data clause associated with no_create operation must "
"match its intent");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -352,6 +476,10 @@ LogicalResult acc::AttachOp::verify() {
if (getDataClause() != acc::DataClause::acc_attach)
return emitError(
"data clause associated with attach operation must match its intent");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -363,6 +491,10 @@ 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");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -374,6 +506,10 @@ LogicalResult acc::DeclareLinkOp::verify() {
if (getDataClause() != acc::DataClause::acc_declare_link)
return emitError(
"data clause associated with link operation must match its intent");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -389,8 +525,12 @@ LogicalResult acc::CopyoutOp::verify() {
return emitError(
"data clause associated with copyout operation must match its intent"
" or specify original clause this operation was decomposed from");
- if (!getVarPtr() || !getAccPtr())
+ if (!getVar() || !getAccVar())
return emitError("must have both host and device pointers");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -414,7 +554,7 @@ LogicalResult acc::DeleteOp::verify() {
return emitError(
"data clause associated with delete operation must match its intent"
" or specify original clause this operation was decomposed from");
- if (!getAccPtr())
+ if (!getAccVar())
return emitError("must have device pointer");
return success();
}
@@ -429,7 +569,7 @@ LogicalResult acc::DetachOp::verify() {
return emitError(
"data clause associated with detach operation must match its intent"
" or specify original clause this operation was decomposed from");
- if (!getAccPtr())
+ if (!getAccVar())
return emitError("must have device pointer");
return success();
}
@@ -444,8 +584,12 @@ LogicalResult acc::UpdateHostOp::verify() {
return emitError(
"data clause associated with host operation must match its intent"
" or specify original clause this operation was decomposed from");
- if (!getVarPtr() || !getAccPtr())
+ if (!getVar() || !getAccVar())
return emitError("must have both host and device pointers");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -458,6 +602,10 @@ LogicalResult acc::UpdateDeviceOp::verify() {
return emitError(
"data clause associated with device operation must match its intent"
" or specify original clause this operation was decomposed from");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -470,6 +618,10 @@ LogicalResult acc::UseDeviceOp::verify() {
return emitError(
"data clause associated with use_device operation must match its intent"
" or specify original clause this operation was decomposed from");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -483,6 +635,10 @@ LogicalResult acc::CacheOp::verify() {
return emitError(
"data clause associated with cache operation must match its intent"
" or specify original clause this operation was decomposed from");
+ if (failed(checkVarAndVarType(*this)))
+ return failure();
+ if (failed(checkVarAndAccVar(*this)))
+ return failure();
return success();
}
@@ -502,7 +658,7 @@ static ParseResult parseRegions(OpAsmParser &parser, OperationState &state,
}
static bool isComputeOperation(Operation *op) {
- return isa<acc::ParallelOp, acc::LoopOp>(op);
+ return isa<ACC_COMPUTE_CONSTRUCT_AND_LOOP_OPS>(op);
}
namespace {
@@ -2917,20 +3073,56 @@ LogicalResult acc::WaitOp::verify() {
// acc dialect utilities
//===----------------------------------------------------------------------===//
-mlir::Value mlir::acc::getVarPtr(mlir::Operation *accDataClauseOp) {
- auto varPtr{llvm::TypeSwitch<mlir::Operation *, mlir::Value>(accDataClauseOp)
+mlir::TypedValue<mlir::acc::PointerLikeType>
+mlir::acc::getVarPtr(mlir::Operation *accDataClauseOp) {
+ auto varPtr{llvm::TypeSwitch<mlir::Operation *,
+ mlir::TypedValue<mlir::acc::PointerLikeType>>(
+ accDataClauseOp)
.Case<ACC_DATA_ENTRY_OPS>(
[&](auto entry) { return entry.getVarPtr(); })
.Case<mlir::acc::CopyoutOp, mlir::acc::UpdateHostOp>(
[&](auto exit) { return exit.getVarPtr(); })
- .Default([&](mlir::Operation *) { return mlir::Value(); })};
+ .Default([&](mlir::Operation *) {
+ return mlir::TypedValue<mlir::acc::PointerLikeType>();
+ })};
return varPtr;
}
-mlir::Value mlir::acc::getAccPtr(mlir::Operation *accDataClauseOp) {
- auto accPtr{llvm::TypeSwitch<mlir::Operation *, mlir::Value>(accDataClauseOp)
+mlir::Value mlir::acc::getVar(mlir::Operation *accDataClauseOp) {
+ auto varPtr{
+ llvm::TypeSwitch<mlir::Operation *, mlir::Value>(accDataClauseOp)
+ .Case<ACC_DATA_ENTRY_OPS>([&](auto entry) { return entry.getVar(); })
+ .Default([&](mlir::Operation *) { return mlir::Value(); })};
+ return varPtr;
+}
+
+mlir::Type mlir::acc::getVarType(mlir::Operation *accDataClauseOp) {
+ auto varType{llvm::TypeSwitch<mlir::Operation *, mlir::Type>(accDataClauseOp)
+ .Case<ACC_DATA_ENTRY_OPS>(
+ [&](auto entry) { return entry.getVarType(); })
+ .Case<mlir::acc::CopyoutOp, mlir::acc::UpdateHostOp>(
+ [&](auto exit) { return exit.getVarType(); })
+ .Default([&](mlir::Operation *) { return mlir::Type(); })};
+ return varType;
+}
+
+mlir::TypedValue<mlir::acc::PointerLikeType>
+mlir::acc::getAccPtr(mlir::Operation *accDataClauseOp) {
+ auto accPtr{llvm::TypeSwitch<mlir::Operation *,
+ mlir::TypedValue<mlir::acc::PointerLikeType>>(
+ accDataClauseOp)
.Case<ACC_DATA_ENTRY_OPS, ACC_DATA_EXIT_OPS>(
[&](auto dataClause) { return dataClause.getAccPtr(); })
+ .Default([&](mlir::Operation *) {
+ return mlir::TypedValue<mlir::acc::PointerLikeType>();
+ })};
+ return accPtr;
+}
+
+mlir::Value mlir::acc::getAccVar(mlir::Operation *accDataClauseOp) {
+ auto accPtr{llvm::TypeSwitch<mlir::Operation *, mlir::Value>(accDataClauseOp)
+ .Case<ACC_DATA_ENTRY_OPS, ACC_DATA_EXIT_OPS>(
+ [&](auto dataClause) { return dataClause.getAccVar(); })
.Default([&](mlir::Operation *) { return mlir::Value(); })};
return accPtr;
}
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCOpsTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCOpsTest.cpp
index fbdada9309d32c..cfb8aa767b6f86 100644
--- a/mlir/unittests/Dialect/OpenACC/OpenACCOpsTest.cpp
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCOpsTest.cpp
@@ -9,9 +9,11 @@
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/OwningOpRef.h"
+#include "mlir/IR/Value.h"
#include "gtest/gtest.h"
using namespace mlir;
@@ -446,10 +448,12 @@ void testShortDataEntryOpBuilders(OpBuilder &b, MLIRContext &context,
OwningOpRef<memref::AllocaOp> varPtrOp =
b.create<memref::AllocaOp>(loc, memrefTy);
- OwningOpRef<Op> op = b.create<Op>(loc, varPtrOp->getResult(),
+ TypedValue<PointerLikeType> varPtr =
+ cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());
+ OwningOpRef<Op> op = b.create<Op>(loc, varPtr,
/*structured=*/true, /*implicit=*/true);
- EXPECT_EQ(op->getVarPtr(), varPtrOp->getResult());
+ EXPECT_EQ(op->getVarPtr(), varPtr);
EXPECT_EQ(op->getType(), memrefTy);
EXPECT_EQ(op->getDataClause(), dataClause);
EXPECT_TRUE(op->getImplicit());
@@ -457,7 +461,7 @@ void testShortDataEntryOpBuilders(OpBuilder &b, MLIRContext &context,
EXPECT_TRUE(op->getBounds().empty());
EXPECT_FALSE(op->getVarPtrPtr());
- OwningOpRef<Op> op2 = b.create<Op>(loc, varPtrOp->getResult(),
+ OwningOpRef<Op> op2 = b.create<Op>(loc, varPtr,
/*structured=*/false, /*implicit=*/false);
EXPECT_FALSE(op2->getImplicit());
EXPECT_FALSE(op2->getStructured());
@@ -467,13 +471,13 @@ void testShortDataEntryOpBuilders(OpBuilder &b, MLIRContext &context,
OwningOpRef<DataBoundsOp> bounds =
b.create<DataBoundsOp>(loc, extent->getResult());
OwningOpRef<Op> opWithBounds =
- b.create<Op>(loc, varPtrOp->getResult(),
+ b.create<Op>(loc, varPtr,
/*structured=*/true, /*implicit=*/true, bounds->getResult());
EXPECT_FALSE(opWithBounds->getBounds().empty());
EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult());
OwningOpRef<Op> opWithName =
- b.create<Op>(loc, varPtrOp->getResult(),
+ b.create<Op>(loc, varPtr,
/*structured=*/true, /*implicit=*/true, "varName");
EXPECT_EQ(opWithName->getNameAttr().str(), "varName");
}
@@ -516,23 +520,26 @@ void testShortDataExitOpBuilders(OpBuilder &b, MLIRContext &context,
auto memrefTy = MemRefType::get({}, b.getI32Type());
OwningOpRef<memref::AllocaOp> varPtrOp =
b.create<memref::AllocaOp>(loc, memrefTy);
+ TypedValue<PointerLikeType> varPtr =
+ cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());
+
OwningOpRef<GetDevicePtrOp> accPtrOp = b.create<GetDevicePtrOp>(
- loc, varPtrOp->getResult(), /*structured=*/true, /*implicit=*/true);
+ loc, varPtr, /*structured=*/true, /*implicit=*/true);
+ TypedValue<PointerLikeType> accPtr =
+ cast<TypedValue<PointerLikeType>>(accPtrOp->getResult());
- OwningOpRef<Op> op =
- b.create<Op>(loc, accPtrOp->getResult(), varPtrOp->getResult(),
- /*structured=*/true, /*implicit=*/true);
+ OwningOpRef<Op> op = b.create<Op>(loc, accPtr, varPtr,
+ /*structured=*/true, /*implicit=*/true);
- EXPECT_EQ(op->getVarPtr(), varPtrOp->getResult());
- EXPECT_EQ(op->getAccPtr(), accPtrOp->getResult());
+ EXPECT_EQ(op->getVarPtr(), varPtr);
+ EXPECT_EQ(op->getAccPtr(), accPtr);
EXPECT_EQ(op->getDataClause(), dataClause);
EXPECT_TRUE(op->getImplicit());
EXPECT_TRUE(op->getStructured());
EXPECT_TRUE(op->getBounds().empty());
- OwningOpRef<Op> op2 =
- b.create<Op>(loc, accPtrOp->getResult(), varPtrOp->getResult(),
- /*structured=*/false, /*implicit=*/false);
+ OwningOpRef<Op> op2 = b.create<Op>(loc, accPtr, varPtr,
+ /*structured=*/false, /*implicit=*/false);
EXPECT_FALSE(op2->getImplicit());
EXPECT_FALSE(op2->getStructured());
@@ -541,13 +548,13 @@ void testShortDataExitOpBuilders(OpBuilder &b, MLIRContext &context,
OwningOpRef<DataBoundsOp> bounds =
b.create<DataBoundsOp>(loc, extent->getResult());
OwningOpRef<Op> opWithBounds =
- b.create<Op>(loc, accPtrOp->getResult(), varPtrOp->getResult(),
+ b.create<Op>(loc, accPtr, varPtr,
/*structured=*/true, /*implicit=*/true, bounds->getResult());
EXPECT_FALSE(opWithBounds->getBounds().empty());
EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult());
OwningOpRef<Op> opWithName =
- b.create<Op>(loc, accPtrOp->getResult(), varPtrOp->getResult(),
+ b.create<Op>(loc, accPtr, varPtr,
/*structured=*/true, /*implicit=*/true, "varName");
EXPECT_EQ(opWithName->getNameAttr().str(), "varName");
}
@@ -565,19 +572,24 @@ void testShortDataExitNoVarPtrOpBuilders(OpBuilder &b, MLIRContext &context,
auto memrefTy = MemRefType::get({}, b.getI32Type());
OwningOpRef<memref::AllocaOp> varPtrOp =
b.create<memref::AllocaOp>(loc, memrefTy);
+ TypedValue<PointerLikeType> varPtr =
+ cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());
+
OwningOpRef<GetDevicePtrOp> accPtrOp = b.create<GetDevicePtrOp>(
- loc, varPtrOp->getResult(), /*structured=*/true, /*implicit=*/true);
+ loc, varPtr, /*structured=*/true, /*implicit=*/true);
+ TypedValue<PointerLikeType> accPtr =
+ cast<TypedValue<PointerLikeType>>(accPtrOp->getResult());
- OwningOpRef<Op> op = b.create<Op>(loc, accPtrOp->getResult(),
+ OwningOpRef<Op> op = b.create<Op>(loc, accPtr,
/*structured=*/true, /*implicit=*/true);
- EXPECT_EQ(op->getAccPtr(), accPtrOp->getResult());
+ EXPECT_EQ(op->getAccPtr(), accPtr);
EXPECT_EQ(op->getDataClause(), dataClause);
EXPECT_TRUE(op->getImplicit());
EXPECT_TRUE(op->getStructured());
EXPECT_TRUE(op->getBounds().empty());
- OwningOpRef<Op> op2 = b.create<Op>(loc, accPtrOp->getResult(),
+ OwningOpRef<Op> op2 = b.create<Op>(loc, accPtr,
/*structured=*/false, /*implicit=*/false);
EXPECT_FALSE(op2->getImplicit());
EXPECT_FALSE(op2->getStructured());
@@ -587,13 +599,13 @@ void testShortDataExitNoVarPtrOpBuilders(OpBuilder &b, MLIRContext &context,
OwningOpRef<DataBoundsOp> bounds =
b.create<DataBoundsOp>(loc, extent->getResult());
OwningOpRef<Op> opWithBounds =
- b.create<Op>(loc, accPtrOp->getResult(),
+ b.create<Op>(loc, accPtr,
/*structured=*/true, /*implicit=*/true, bounds->getResult());
EXPECT_FALSE(opWithBounds->getBounds().empty());
EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult());
OwningOpRef<Op> opWithName =
- b.create<Op>(loc, accPtrOp->getResult(),
+ b.create<Op>(loc, accPtr,
/*structured=*/true, /*implicit=*/true, "varName");
EXPECT_EQ(opWithName->getNameAttr().str(), "varName");
}
@@ -604,3 +616,75 @@ TEST_F(OpenACCOpsTest, shortDataExitOpNoVarPtrBuilder) {
testShortDataExitNoVarPtrOpBuilders<DetachOp>(b, context, loc,
DataClause::acc_detach);
}
+
+template <typename Op>
+void testShortDataEntryOpBuildersMappableVar(OpBuilder &b, MLIRContext &context,
+ Location loc,
+ DataClause dataClause) {
+ auto int64Ty = b.getI64Type();
+ auto memrefTy = MemRefType::get({}, int64Ty);
+ OwningOpRef<memref::AllocaOp> varPtrOp =
+ b.create<memref::AllocaOp>(loc, memrefTy);
+ SmallVector<Value> indices;
+ OwningOpRef<memref::LoadOp> loadVarOp =
+ b.create<memref::LoadOp>(loc, int64Ty, varPtrOp->getResult(), indices);
+
+ EXPECT_TRUE(isMappableType(loadVarOp->getResult().getType()));
+ TypedValue<MappableType> var =
+ cast<TypedValue<MappableType>>(loadVarOp->getResult());
+ OwningOpRef<Op> op = b.create<Op>(loc, var,
+ /*structured=*/true, /*implicit=*/true);
+
+ EXPECT_EQ(op->getVar(), var);
+ EXPECT_EQ(op->getVarPtr(), nullptr);
+ EXPECT_EQ(op->getType(), int64Ty);
+ EXPECT_EQ(op->getVarType(), int64Ty);
+ EXPECT_EQ(op->getDataClause(), dataClause);
+ EXPECT_TRUE(op->getImplicit());
+ EXPECT_TRUE(op->getStructured());
+ EXPECT_TRUE(op->getBounds().empty());
+ EXPECT_FALSE(op->getVarPtrPtr());
+}
+
+struct IntegerOpenACCMappableModel
+ : public mlir::acc::MappableType::ExternalModel<IntegerOpenACCMappableModel,
+ IntegerType> {};
+
+TEST_F(OpenACCOpsTest, mappableTypeBuilderDataEntry) {
+ // First, set up the test by attaching MappableInterface to IntegerType.
+ IntegerType i64ty = IntegerType::get(&context, 8);
+ ASSERT_FALSE(isMappableType(i64ty));
+ IntegerType::attachInterface<IntegerOpenACCMappableModel>(context);
+ ASSERT_TRUE(isMappableType(i64ty));
+
+ testShortDataEntryOpBuildersMappableVar<PrivateOp>(b, context, loc,
+ DataClause::acc_private);
+ testShortDataEntryOpBuildersMappableVar<FirstprivateOp>(
+ b, context, loc, DataClause::acc_firstprivate);
+ testShortDataEntryOpBuildersMappableVar<ReductionOp>(
+ b, context, loc, DataClause::acc_reduction);
+ testShortDataEntryOpBuildersMappableVar<DevicePtrOp>(
+ b, context, loc, DataClause::acc_deviceptr);
+ testShortDataEntryOpBuildersMappableVar<PresentOp>(b, context, loc,
+ DataClause::acc_present);
+ testShortDataEntryOpBuildersMappableVar<CopyinOp>(b, context, loc,
+ DataClause::acc_copyin);
+ testShortDataEntryOpBuildersMappableVar<CreateOp>(b, context, loc,
+ DataClause::acc_create);
+ testShortDataEntryOpBuildersMappableVar<NoCreateOp>(
+ b, context, loc, DataClause::acc_no_create);
+ testShortDataEntryOpBuildersMappableVar<AttachOp>(b, context, loc,
+ DataClause::acc_attach);
+ testShortDataEntryOpBuildersMappableVar<GetDevicePtrOp>(
+ b, context, loc, DataClause::acc_getdeviceptr);
+ testShortDataEntryOpBuildersMappableVar<UpdateDeviceOp>(
+ b, context, loc, DataClause::acc_update_device);
+ testShortDataEntryOpBuildersMappableVar<UseDeviceOp>(
+ b, context, loc, DataClause::acc_use_device);
+ testShortDataEntryOpBuildersMappableVar<DeclareDeviceResidentOp>(
+ b, context, loc, DataClause::acc_declare_device_resident);
+ testShortDataEntryOpBuildersMappableVar<DeclareLinkOp>(
+ b, context, loc, DataClause::acc_declare_link);
+ testShortDataEntryOpBuildersMappableVar<CacheOp>(b, context, loc,
+ DataClause::acc_cache);
+}
>From 6ff4fa66b7c8d408ffc7271dfd06bf83b19cd09a Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Wed, 8 Jan 2025 12:41:43 -0800
Subject: [PATCH 2/2] Fix indent
---
mlir/docs/Dialects/OpenACCDialect.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/mlir/docs/Dialects/OpenACCDialect.md b/mlir/docs/Dialects/OpenACCDialect.md
index 39218a9676ff34..9e85d66ba340fd 100755
--- a/mlir/docs/Dialects/OpenACCDialect.md
+++ b/mlir/docs/Dialects/OpenACCDialect.md
@@ -284,7 +284,7 @@ Data clause operations (eg. `acc.copyin`) rely on the following type
considerations:
* type of acc data clause operation input `var`
- The type of `var` must be one with `PointerLikeType` or `MappableType`
- interfaces attached. The first, `PointerLikeType`, is useful because
+ interfaces attached. The first, `PointerLikeType`, is useful because
the OpenACC memory model distinguishes between host and device memory
explicitly - and the mapping between the two is done through pointers. Thus,
by explicitly requiring it in the dialect, the appropriate language
@@ -302,8 +302,8 @@ considerations:
since the `acc` dialect must live within another dialect whose type
system is unknown to it.
* variable type captured in `varType`
- - When `var`'s type is `PointerLikeType`, the actual type of the target
- may be lost. More specifically, dialects like `llvm` which use opaque
+ - When `var`'s type is `PointerLikeType`, the actual type of the target
+ may be lost. More specifically, dialects like `llvm` which use opaque
pointers, do not record the target variable's type. The use of this field
bridges this gap.
* type of decomposed clauses
More information about the Mlir-commits
mailing list