Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -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]>;

Expand Down
36 changes: 35 additions & 1 deletion mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}]
>,
];
}

Expand Down Expand Up @@ -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
Expand All @@ -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;
}]
>,
];
}

Expand Down
33 changes: 32 additions & 1 deletion mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
};

Expand Down