[Mlir-commits] [mlir] [acc][mlir] Add functionality for categorizing OpenACC variable types (PR #126167)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Feb 6 17:59:43 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-openacc
Author: Razvan Lupusoru (razvanlupusoru)
<details>
<summary>Changes</summary>
OpenACC specification describes the following type categories: scalar, array, composite, and aggregate (which includes arrays, composites, and others such as Fortran pointer/allocatable).
Decision for how to do implicit mapping is dependent on a variable's category. Since acc dialect's only means of distinguishing between types is through the interfaces attached, add API to be able to get the type category.
In addition to defining the new API, attempt to provide a base implementation for memref which matches what OpenACC spec describes.
---
Full diff: https://github.com/llvm/llvm-project/pull/126167.diff
3 Files Affected:
- (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td (+68)
- (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td (+35-1)
- (modified) mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp (+32-1)
``````````diff
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index df0d408d0f0e1e3..42da20251c19087 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -65,6 +65,74 @@ def OpenACC_ReductionOperatorAttr : EnumAttr<OpenACC_Dialect,
let assemblyFormat = [{ ```<` $value `>` }];
}
+// OpenACC variable type categorization. This is needed because OpenACC
+// dialect is used with other dialects, and each dialect defines its own
+// types. Thus, in order to be able to classify types and apply right semantics,
+// it is needed to ensure the types can be categorized.
+def OpenACC_VariableTypeUncategorized : I32BitEnumAttrCaseNone<"uncategorized">;
+
+// The OpenACC spec definition of scalar type is as follows (from 3.3 spec,
+// line 5454):
+// Scalar datatype - an intrinsic or built-in datatype that is not an array or
+// aggregate datatype. In Fortran, scalar datatypes are integer, real, double
+// precision, complex, or logical. In C, scalar datatypes are char (signed or
+// unsigned), int (signed or unsigned, with optional short, long or long long
+// attribute), enum, float, double, long double, Complex (with optional float
+// or long attribute), or any pointer datatype. In C++, scalar datatypes are
+// char (signed or unsigned), wchar t, int (signed or unsigned, with optional
+// short, long or long long attribute), enum, bool, float, double, long double,
+// or any pointer datatype. Not all implementations or targets will support all
+// of these datatypes.
+// From an MLIR type perspective, the types that those language types map to
+// will be categorized as scalar.
+def OpenACC_VariableTypeScalar : I32BitEnumAttrCaseBit<"scalar", 0>;
+
+// Not in OpenACC spec glossary as its own definition but used throughout the
+// spec. One definition of array that can be assumed for purposes of type
+// categorization is that it is a collection of elements of same type.
+def OpenACC_VariableTypeArray : I32BitEnumAttrCaseBit<"array", 1>;
+
+// The OpenACC spec definition of composite type is as follows (from 3.3 spec,
+// line 5354):
+// Composite datatype - a derived type in Fortran, or a struct or union type in
+// C, or a class, struct, or union type in C++. (This is different from the use
+// of the term composite data type in the C and C++ languages.)
+def OpenACC_VariableTypeComposite : I32BitEnumAttrCaseBit<"composite", 2>;
+
+// The OpenACC spec uses the type category "aggregate" to capture both arrays
+// and composite types. However, it includes types which do not fall in either
+// of those categories. Thus create a case for the others.
+// For example, reading the definition of "Aggregate Variables" in the 3.3
+// spec line 5346 shows this distinction:
+// Aggregate variables - a variable of any non-scalar datatype, including array
+// or composite variables. In Fortran, this includes any variable with
+// allocatable or pointer attribute and character variables
+def OpenACC_VariableTypeOtherNonScalar : I32BitEnumAttrCaseBit<"nonscalar", 3>;
+
+// The OpenACC spec definition of aggregate type is as follows (from 3.3 spec,
+// line 5342):
+// Aggregate datatype - any non-scalar datatype such as array and composite
+// datatypes. In Fortran, aggregate datatypes include arrays, derived types,
+// character types. In C, aggregate datatypes include arrays, targets of
+// pointers, structs, and unions. In C++, aggregate datatypes include arrays,
+// targets of pointers, classes, structs, and unions.
+def OpenACC_VariableTypeAggregate : I32BitEnumAttrCaseGroup<"aggregate",
+ [OpenACC_VariableTypeArray, OpenACC_VariableTypeComposite,
+ OpenACC_VariableTypeOtherNonScalar]>;
+
+def OpenACC_VariableTypeCategory : I32BitEnumAttr<
+ "VariableTypeCategory",
+ "Captures different type categories described in OpenACC spec",
+ [
+ OpenACC_VariableTypeUncategorized, OpenACC_VariableTypeScalar,
+ OpenACC_VariableTypeArray, OpenACC_VariableTypeComposite,
+ OpenACC_VariableTypeOtherNonScalar, OpenACC_VariableTypeAggregate]> {
+ let separator = ",";
+ let cppNamespace = "::mlir::acc";
+ let genSpecializedAttr = 0;
+ let printBitEnumPrimaryGroups = 1;
+}
+
// Type used in operation below.
def IntOrIndex : AnyTypeOf<[AnyInteger, Index]>;
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
index bec46be89f0585a..fa66a4746f7da6a 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
@@ -28,6 +28,28 @@ def OpenACC_PointerLikeTypeInterface : TypeInterface<"PointerLikeType"> {
/*retTy=*/"::mlir::Type",
/*methodName=*/"getElementType"
>,
+ InterfaceMethod<
+ /*description=*/[{
+ Returns the type category of the pointee. The `var` is provided because
+ a dialect's type system may be incomplete. For example, consider a
+ dialect which computes interior pointers - so a float array element
+ may be represented as `ptr<f32>`. The type system says the pointee
+ is `f32` but this is not a scalar from the point-of-view of OpenACC.
+ It is an array element and thus the appropriate type category is
+ "array" - therefore being able to look up how a variable is computed
+ is important for a complete type determination.
+ The `varType` is provided in cases where a dialect's type system
+ erased the target type.
+ }],
+ /*retTy=*/"::mlir::acc::VariableTypeCategory",
+ /*methodName=*/"getPointeeTypeCategory",
+ /*args=*/(ins "::mlir::TypedValue<::mlir::acc::PointerLikeType>":$varPtr,
+ "::mlir::Type":$varType),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/[{
+ return ::mlir::acc::VariableTypeCategory::uncategorized;
+ }]
+ >,
];
}
@@ -106,7 +128,7 @@ def OpenACC_MappableTypeInterface : TypeInterface<"MappableType"> {
return {};
}]
>,
- InterfaceMethod<
+ InterfaceMethod<
/*description=*/[{
Returns explicit `acc.bounds` operations that envelop the whole
data structure. These operations are inserted using the provided builder
@@ -121,6 +143,18 @@ def OpenACC_MappableTypeInterface : TypeInterface<"MappableType"> {
return {};
}]
>,
+ InterfaceMethod<
+ /*description=*/[{
+ Returns the OpenACC type category.
+ }],
+ /*retTy=*/"::mlir::acc::VariableTypeCategory",
+ /*methodName=*/"getTypeCategory",
+ /*args=*/(ins "::mlir::Value":$var),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/[{
+ return ::mlir::acc::VariableTypeCategory::uncategorized;
+ }]
+ >,
];
}
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index 9ebce4db854dc64..aaa3db22110ac72 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -32,11 +32,42 @@ using namespace acc;
#include "mlir/Dialect/OpenACCMPCommon/Interfaces/OpenACCMPOpsInterfaces.cpp.inc"
namespace {
+
+static bool isScalarLikeType(Type type) {
+ return type.isIntOrIndexOrFloat() || isa<ComplexType>(type);
+}
+
struct MemRefPointerLikeModel
: public PointerLikeType::ExternalModel<MemRefPointerLikeModel,
MemRefType> {
Type getElementType(Type pointer) const {
- return llvm::cast<MemRefType>(pointer).getElementType();
+ return cast<MemRefType>(pointer).getElementType();
+ }
+ mlir::acc::VariableTypeCategory
+ getPointeeTypeCategory(Type pointer, TypedValue<PointerLikeType> varPtr,
+ Type varType) const {
+ if (auto mappableTy = dyn_cast<MappableType>(varType)) {
+ return mappableTy.getTypeCategory(varPtr);
+ }
+ auto memrefTy = cast<MemRefType>(pointer);
+ if (!memrefTy.hasRank()) {
+ // This memref is unranked - aka it could have any rank, including a
+ // rank of 0 which could mean scalar. For now, return uncategorized.
+ return mlir::acc::VariableTypeCategory::uncategorized;
+ }
+
+ if (memrefTy.getRank() == 0) {
+ if (isScalarLikeType(memrefTy.getElementType())) {
+ return mlir::acc::VariableTypeCategory::scalar;
+ }
+ // Zero-rank non-scalar - need further analysis to determine the type
+ // category. For now, return uncategorized.
+ return mlir::acc::VariableTypeCategory::uncategorized;
+ }
+
+ // It has a rank - must be an array.
+ assert(memrefTy.getRank() > 0 && "rank expected to be positive");
+ return mlir::acc::VariableTypeCategory::array;
}
};
``````````
</details>
https://github.com/llvm/llvm-project/pull/126167
More information about the Mlir-commits
mailing list