[mlir] use TypeSize and uint64_t in DataLayout (#72874)

Data layout queries may be issued for types whose size exceeds the range
of 32-bit integer as well as for types that don't have a size known at
compile time, such as scalable vectors. Use best practices from LLVM IR
and adopt `llvm::TypeSize` for size-related queries and `uint64_t` for
alignment-related queries.

See #72678.
This commit is contained in:
Oleksandr "Alex" Zinenko 2023-11-21 16:12:27 +01:00 committed by GitHub
parent 49f0070237
commit 8134a8fc3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 318 additions and 247 deletions

View File

@ -73,10 +73,10 @@ class DataLayout {
public:
explicit DataLayout(DataLayoutOpInterface scope);
unsigned getTypeSize(Type type) const;
unsigned getTypeSizeInBits(Type type) const;
unsigned getTypeABIAlignment(Type type) const;
unsigned getTypePreferredAlignment(Type type) const;
llvm::TypeSize getTypeSize(Type type) const;
llvm::TypeSize getTypeSizeInBits(Type type) const;
uint64_t getTypeABIAlignment(Type type) const;
uint64_t getTypePreferredAlignment(Type type) const;
};
```

View File

@ -186,13 +186,13 @@ public:
/// Hooks for DataLayoutTypeInterface. Should not be called directly. Obtain a
/// DataLayout instance and query it instead.
unsigned getTypeSizeInBits(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const;
llvm::TypeSize getTypeSizeInBits(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const;
unsigned getABIAlignment(const DataLayout &dataLayout,
uint64_t getABIAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const;
unsigned getPreferredAlignment(const DataLayout &dataLayout,
uint64_t getPreferredAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const;
bool areCompatible(DataLayoutEntryListRef oldLayout,
@ -288,7 +288,7 @@ enum class PtrDLEntryPos { Size = 0, Abi = 1, Preferred = 2, Index = 3 };
/// Returns `std::nullopt` if `pos` is not present in the entry.
/// Currently only `PtrDLEntryPos::Index` is optional, and all other positions
/// may be assumed to be present.
std::optional<unsigned> extractPointerSpecValue(Attribute attr,
std::optional<uint64_t> extractPointerSpecValue(Attribute attr,
PtrDLEntryPos pos);
} // namespace LLVM

View File

@ -18,6 +18,7 @@
#include "mlir/IR/DialectInterface.h"
#include "mlir/IR/OpDefinition.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/TypeSize.h"
namespace mlir {
class DataLayout;
@ -34,25 +35,25 @@ class ModuleOp;
namespace detail {
/// Default handler for the type size request. Computes results for built-in
/// types and dispatches to the DataLayoutTypeInterface for other types.
unsigned getDefaultTypeSize(Type type, const DataLayout &dataLayout,
DataLayoutEntryListRef params);
llvm::TypeSize getDefaultTypeSize(Type type, const DataLayout &dataLayout,
DataLayoutEntryListRef params);
/// Default handler for the type size in bits request. Computes results for
/// built-in types and dispatches to the DataLayoutTypeInterface for other
/// types.
unsigned getDefaultTypeSizeInBits(Type type, const DataLayout &dataLayout,
DataLayoutEntryListRef params);
llvm::TypeSize getDefaultTypeSizeInBits(Type type, const DataLayout &dataLayout,
DataLayoutEntryListRef params);
/// Default handler for the required alignemnt request. Computes results for
/// Default handler for the required alignment request. Computes results for
/// built-in types and dispatches to the DataLayoutTypeInterface for other
/// types.
unsigned getDefaultABIAlignment(Type type, const DataLayout &dataLayout,
uint64_t getDefaultABIAlignment(Type type, const DataLayout &dataLayout,
ArrayRef<DataLayoutEntryInterface> params);
/// Default handler for the preferred alignemnt request. Computes results for
/// Default handler for the preferred alignment request. Computes results for
/// built-in types and dispatches to the DataLayoutTypeInterface for other
/// types.
unsigned
uint64_t
getDefaultPreferredAlignment(Type type, const DataLayout &dataLayout,
ArrayRef<DataLayoutEntryInterface> params);
@ -62,7 +63,7 @@ Attribute getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry);
/// Default handler for the stack alignment request. Dispatches to the
/// DataLayoutInterface if specified, otherwise returns the default.
unsigned getDefaultStackAlignment(DataLayoutEntryInterface entry);
uint64_t getDefaultStackAlignment(DataLayoutEntryInterface entry);
/// Given a list of data layout entries, returns a new list containing the
/// entries with keys having the given type ID, i.e. belonging to the same type
@ -85,6 +86,10 @@ LogicalResult verifyDataLayoutOp(Operation *op);
/// entry verifiers, and then to the verifiers implemented by the relevant type
/// and dialect interfaces for type and identifier keys respectively.
LogicalResult verifyDataLayoutSpec(DataLayoutSpecInterface spec, Location loc);
/// Divides the known min value of the numerator by the denominator and rounds
/// the result up to the next integer. Preserves the scalable flag.
llvm::TypeSize divideCeil(llvm::TypeSize numerator, uint64_t denominator);
} // namespace detail
} // namespace mlir
@ -156,16 +161,16 @@ public:
static DataLayout closest(Operation *op);
/// Returns the size of the given type in the current scope.
unsigned getTypeSize(Type t) const;
llvm::TypeSize getTypeSize(Type t) const;
/// Returns the size in bits of the given type in the current scope.
unsigned getTypeSizeInBits(Type t) const;
llvm::TypeSize getTypeSizeInBits(Type t) const;
/// Returns the required alignment of the given type in the current scope.
unsigned getTypeABIAlignment(Type t) const;
uint64_t getTypeABIAlignment(Type t) const;
/// Returns the preferred of the given type in the current scope.
unsigned getTypePreferredAlignment(Type t) const;
uint64_t getTypePreferredAlignment(Type t) const;
/// Returns the memory space used for AllocaOps.
Attribute getAllocaMemorySpace() const;
@ -174,7 +179,7 @@ public:
/// stack variables should be limited to the natural stack alignment to
/// prevent dynamic stack alignment. Returns zero if the stack alignment is
/// unspecified.
unsigned getStackAlignment() const;
uint64_t getStackAlignment() const;
private:
/// Combined layout spec at the given scope.
@ -193,16 +198,16 @@ private:
Operation *scope;
/// Caches for individual requests.
mutable DenseMap<Type, unsigned> sizes;
mutable DenseMap<Type, unsigned> bitsizes;
mutable DenseMap<Type, unsigned> abiAlignments;
mutable DenseMap<Type, unsigned> preferredAlignments;
mutable DenseMap<Type, llvm::TypeSize> sizes;
mutable DenseMap<Type, llvm::TypeSize> bitsizes;
mutable DenseMap<Type, uint64_t> abiAlignments;
mutable DenseMap<Type, uint64_t> preferredAlignments;
/// Cache for alloca memory space.
mutable std::optional<Attribute> allocaMemorySpace;
/// Cache for stack alignment.
mutable std::optional<unsigned> stackAlignment;
mutable std::optional<uint64_t> stackAlignment;
};
} // namespace mlir

View File

@ -213,22 +213,22 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> {
/*description=*/"Returns the size of the given type computed using the "
"relevant entries. The data layout object can be used "
"for recursive queries.",
/*retTy=*/"unsigned",
/*retTy=*/"::llvm::TypeSize",
/*methodName=*/"getTypeSize",
/*args=*/(ins "::mlir::Type":$type,
"const ::mlir::DataLayout &":$dataLayout,
"::mlir::DataLayoutEntryListRef":$params),
/*methodBody=*/"",
/*defaultImplementation=*/[{
unsigned bits = ConcreteOp::getTypeSizeInBits(type, dataLayout, params);
return ::llvm::divideCeil(bits, 8);
::llvm::TypeSize bits = ConcreteOp::getTypeSizeInBits(type, dataLayout, params);
return ::mlir::detail::divideCeil(bits, 8u);
}]
>,
StaticInterfaceMethod<
/*description=*/"Returns the size of the given type in bits computed "
"using the relevant entries. The data layout object can "
"be used for recursive queries.",
/*retTy=*/"unsigned",
/*retTy=*/"::llvm::TypeSize",
/*methodName=*/"getTypeSizeInBits",
/*args=*/(ins "::mlir::Type":$type,
"const ::mlir::DataLayout &":$dataLayout,
@ -243,7 +243,7 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> {
/*description=*/"Returns the alignment required by the ABI for the given "
"type computed using the relevant entries. The data "
"layout object can be used for recursive queries.",
/*retTy=*/"unsigned",
/*retTy=*/"uint64_t",
/*methodName=*/"getTypeABIAlignment",
/*args=*/(ins "::mlir::Type":$type,
"const ::mlir::DataLayout &":$dataLayout,
@ -257,7 +257,7 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> {
/*description=*/"Returns the alignment preferred by the given type "
"computed using the relevant entries. The data layout"
"object can be used for recursive queries.",
/*retTy=*/"unsigned",
/*retTy=*/"uint64_t",
/*methodName=*/"getTypePreferredAlignment",
/*args=*/(ins "::mlir::Type":$type,
"const ::mlir::DataLayout &":$dataLayout,
@ -284,7 +284,7 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> {
/*description=*/"Returns the natural stack alignment in bits computed "
"using the relevant entries. The data layout object "
"can be used for recursive queries.",
/*retTy=*/"unsigned",
/*retTy=*/"uint64_t",
/*methodName=*/"getStackAlignment",
/*args=*/(ins "::mlir::DataLayoutEntryInterface":$entry),
/*methodBody=*/"",
@ -331,19 +331,19 @@ def DataLayoutTypeInterface : TypeInterface<"DataLayoutTypeInterface"> {
let methods = [
InterfaceMethod<
/*description=*/"Returns the size of this type in bytes.",
/*retTy=*/"unsigned",
/*retTy=*/"::llvm::TypeSize",
/*methodName=*/"getTypeSize",
/*args=*/(ins "const ::mlir::DataLayout &":$dataLayout,
"::mlir::DataLayoutEntryListRef":$params),
/*methodBody=*/"",
/*defaultImplementation=*/[{
unsigned bits = $_type.getTypeSizeInBits(dataLayout, params);
return ::llvm::divideCeil(bits, 8);
::llvm::TypeSize bits = $_type.getTypeSizeInBits(dataLayout, params);
return ::mlir::detail::divideCeil(bits, 8u);
}]
>,
InterfaceMethod<
/*description=*/"Returns the size of this type in bits.",
/*retTy=*/"unsigned",
/*retTy=*/"::llvm::TypeSize",
/*methodName=*/"getTypeSizeInBits",
/*args=*/(ins "const ::mlir::DataLayout &":$dataLayout,
"::mlir::DataLayoutEntryListRef":$params)
@ -351,7 +351,7 @@ def DataLayoutTypeInterface : TypeInterface<"DataLayoutTypeInterface"> {
InterfaceMethod<
/*description=*/"Returns the ABI-required alignment for this type, "
"in bytes",
/*retTy=*/"unsigned",
/*retTy=*/"uint64_t",
/*methodName=*/"getABIAlignment",
/*args=*/(ins "const ::mlir::DataLayout &":$dataLayout,
"::mlir::DataLayoutEntryListRef":$params)
@ -359,7 +359,7 @@ def DataLayoutTypeInterface : TypeInterface<"DataLayoutTypeInterface"> {
InterfaceMethod<
/*description=*/"Returns the preferred alignment for this type, "
"in bytes.",
/*retTy=*/"unsigned",
/*retTy=*/"uint64_t",
/*methodName=*/"getPreferredAlignment",
/*args=*/(ins "const ::mlir::DataLayout &":$dataLayout,
"::mlir::DataLayoutEntryListRef":$params)

View File

@ -27,7 +27,7 @@
using namespace mlir;
using namespace mlir::LLVM;
constexpr const static unsigned kBitsInByte = 8;
constexpr const static uint64_t kBitsInByte = 8;
//===----------------------------------------------------------------------===//
// custom<FunctionTypes>
@ -178,24 +178,25 @@ LLVMArrayType::verify(function_ref<InFlightDiagnostic()> emitError,
//===----------------------------------------------------------------------===//
// DataLayoutTypeInterface
unsigned LLVMArrayType::getTypeSizeInBits(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
return kBitsInByte * getTypeSize(dataLayout, params);
llvm::TypeSize
LLVMArrayType::getTypeSizeInBits(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
return llvm::TypeSize::Fixed(kBitsInByte * getTypeSize(dataLayout, params));
}
unsigned LLVMArrayType::getTypeSize(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
llvm::TypeSize LLVMArrayType::getTypeSize(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
return llvm::alignTo(dataLayout.getTypeSize(getElementType()),
dataLayout.getTypeABIAlignment(getElementType())) *
getNumElements();
}
unsigned LLVMArrayType::getABIAlignment(const DataLayout &dataLayout,
uint64_t LLVMArrayType::getABIAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
return dataLayout.getTypeABIAlignment(getElementType());
}
unsigned
uint64_t
LLVMArrayType::getPreferredAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
return dataLayout.getTypePreferredAlignment(getElementType());
@ -254,23 +255,23 @@ LLVMFunctionType::verify(function_ref<InFlightDiagnostic()> emitError,
//===----------------------------------------------------------------------===//
// DataLayoutTypeInterface
constexpr const static unsigned kDefaultPointerSizeBits = 64;
constexpr const static unsigned kDefaultPointerAlignment = 8;
constexpr const static uint64_t kDefaultPointerSizeBits = 64;
constexpr const static uint64_t kDefaultPointerAlignment = 8;
std::optional<unsigned> mlir::LLVM::extractPointerSpecValue(Attribute attr,
std::optional<uint64_t> mlir::LLVM::extractPointerSpecValue(Attribute attr,
PtrDLEntryPos pos) {
auto spec = llvm::cast<DenseIntElementsAttr>(attr);
auto idx = static_cast<unsigned>(pos);
auto spec = cast<DenseIntElementsAttr>(attr);
auto idx = static_cast<int64_t>(pos);
if (idx >= spec.size())
return std::nullopt;
return spec.getValues<unsigned>()[idx];
return spec.getValues<uint64_t>()[idx];
}
/// Returns the part of the data layout entry that corresponds to `pos` for the
/// given `type` by interpreting the list of entries `params`. For the pointer
/// type in the default address space, returns the default value if the entries
/// do not provide a custom one, for other address spaces returns std::nullopt.
static std::optional<unsigned>
static std::optional<uint64_t>
getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type,
PtrDLEntryPos pos) {
// First, look for the entry for the pointer in the current address space.
@ -278,8 +279,8 @@ getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type,
for (DataLayoutEntryInterface entry : params) {
if (!entry.isTypeEntry())
continue;
if (llvm::cast<LLVMPointerType>(entry.getKey().get<Type>())
.getAddressSpace() == type.getAddressSpace()) {
if (cast<LLVMPointerType>(entry.getKey().get<Type>()).getAddressSpace() ==
type.getAddressSpace()) {
currentEntry = entry.getValue();
break;
}
@ -299,31 +300,31 @@ getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type,
return std::nullopt;
}
unsigned
llvm::TypeSize
LLVMPointerType::getTypeSizeInBits(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
if (std::optional<unsigned> size =
if (std::optional<uint64_t> size =
getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Size))
return *size;
return llvm::TypeSize::Fixed(*size);
// For other memory spaces, use the size of the pointer to the default memory
// space.
return dataLayout.getTypeSizeInBits(get(getContext()));
}
unsigned LLVMPointerType::getABIAlignment(const DataLayout &dataLayout,
uint64_t LLVMPointerType::getABIAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
if (std::optional<unsigned> alignment =
if (std::optional<uint64_t> alignment =
getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Abi))
return *alignment;
return dataLayout.getTypeABIAlignment(get(getContext()));
}
unsigned
uint64_t
LLVMPointerType::getPreferredAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
if (std::optional<unsigned> alignment =
if (std::optional<uint64_t> alignment =
getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Preferred))
return *alignment;
@ -335,8 +336,8 @@ bool LLVMPointerType::areCompatible(DataLayoutEntryListRef oldLayout,
for (DataLayoutEntryInterface newEntry : newLayout) {
if (!newEntry.isTypeEntry())
continue;
unsigned size = kDefaultPointerSizeBits;
unsigned abi = kDefaultPointerAlignment;
uint64_t size = kDefaultPointerSizeBits;
uint64_t abi = kDefaultPointerAlignment;
auto newType = llvm::cast<LLVMPointerType>(newEntry.getKey().get<Type>());
const auto *it =
llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
@ -360,8 +361,8 @@ bool LLVMPointerType::areCompatible(DataLayoutEntryListRef oldLayout,
}
Attribute newSpec = llvm::cast<DenseIntElementsAttr>(newEntry.getValue());
unsigned newSize = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Size);
unsigned newAbi = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Abi);
uint64_t newSize = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Size);
uint64_t newAbi = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Abi);
if (size != newSize || abi < newAbi || abi % newAbi != 0)
return false;
}
@ -373,13 +374,17 @@ LogicalResult LLVMPointerType::verifyEntries(DataLayoutEntryListRef entries,
for (DataLayoutEntryInterface entry : entries) {
if (!entry.isTypeEntry())
continue;
auto key = entry.getKey().get<Type>();
auto values = llvm::dyn_cast<DenseIntElementsAttr>(entry.getValue());
if (!values || (values.size() != 3 && values.size() != 4)) {
return emitError(loc)
<< "expected layout attribute for " << entry.getKey().get<Type>()
<< "expected layout attribute for " << key
<< " to be a dense integer elements attribute with 3 or 4 "
"elements";
}
if (!values.getElementType().isInteger(64))
return emitError(loc) << "expected i64 parameters for " << key;
if (extractPointerSpecValue(values, PtrDLEntryPos::Abi) >
extractPointerSpecValue(values, PtrDLEntryPos::Preferred)) {
return emitError(loc) << "preferred alignment is expected to be at least "
@ -484,16 +489,16 @@ LLVMStructType::verify(function_ref<InFlightDiagnostic()> emitError,
return success();
}
unsigned
llvm::TypeSize
LLVMStructType::getTypeSizeInBits(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
unsigned structSize = 0;
unsigned structAlignment = 1;
auto structSize = llvm::TypeSize::Fixed(0);
uint64_t structAlignment = 1;
for (Type element : getBody()) {
unsigned elementAlignment =
uint64_t elementAlignment =
isPacked() ? 1 : dataLayout.getTypeABIAlignment(element);
// Add padding to the struct size to align it to the abi alignment of the
// element type before than adding the size of the element
// element type before than adding the size of the element.
structSize = llvm::alignTo(structSize, elementAlignment);
structSize += dataLayout.getTypeSize(element);
@ -511,7 +516,7 @@ namespace {
enum class StructDLEntryPos { Abi = 0, Preferred = 1 };
} // namespace
static std::optional<unsigned>
static std::optional<uint64_t>
getStructDataLayoutEntry(DataLayoutEntryListRef params, LLVMStructType type,
StructDLEntryPos pos) {
const auto *currentEntry =
@ -523,14 +528,14 @@ getStructDataLayoutEntry(DataLayoutEntryListRef params, LLVMStructType type,
auto attr = llvm::cast<DenseIntElementsAttr>(currentEntry->getValue());
if (pos == StructDLEntryPos::Preferred &&
attr.size() <= static_cast<unsigned>(StructDLEntryPos::Preferred))
attr.size() <= static_cast<int64_t>(StructDLEntryPos::Preferred))
// If no preferred was specified, fall back to abi alignment
pos = StructDLEntryPos::Abi;
return attr.getValues<unsigned>()[static_cast<unsigned>(pos)];
return attr.getValues<uint64_t>()[static_cast<size_t>(pos)];
}
static unsigned calculateStructAlignment(const DataLayout &dataLayout,
static uint64_t calculateStructAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params,
LLVMStructType type,
StructDLEntryPos pos) {
@ -541,36 +546,36 @@ static unsigned calculateStructAlignment(const DataLayout &dataLayout,
// The alignment requirement of a struct is equal to the strictest alignment
// requirement of its elements.
unsigned structAlignment = 1;
uint64_t structAlignment = 1;
for (Type iter : type.getBody()) {
structAlignment =
std::max(dataLayout.getTypeABIAlignment(iter), structAlignment);
}
// Entries are only allowed to be stricter than the required alignment
if (std::optional<unsigned> entryResult =
if (std::optional<uint64_t> entryResult =
getStructDataLayoutEntry(params, type, pos))
return std::max(*entryResult / kBitsInByte, structAlignment);
return structAlignment;
}
unsigned LLVMStructType::getABIAlignment(const DataLayout &dataLayout,
uint64_t LLVMStructType::getABIAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
return calculateStructAlignment(dataLayout, params, *this,
StructDLEntryPos::Abi);
}
unsigned
uint64_t
LLVMStructType::getPreferredAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
return calculateStructAlignment(dataLayout, params, *this,
StructDLEntryPos::Preferred);
}
static unsigned extractStructSpecValue(Attribute attr, StructDLEntryPos pos) {
static uint64_t extractStructSpecValue(Attribute attr, StructDLEntryPos pos) {
return llvm::cast<DenseIntElementsAttr>(attr)
.getValues<unsigned>()[static_cast<unsigned>(pos)];
.getValues<uint64_t>()[static_cast<size_t>(pos)];
}
bool LLVMStructType::areCompatible(DataLayoutEntryListRef oldLayout,
@ -586,9 +591,9 @@ bool LLVMStructType::areCompatible(DataLayoutEntryListRef oldLayout,
if (previousEntry == oldLayout.end())
continue;
unsigned abi = extractStructSpecValue(previousEntry->getValue(),
uint64_t abi = extractStructSpecValue(previousEntry->getValue(),
StructDLEntryPos::Abi);
unsigned newAbi =
uint64_t newAbi =
extractStructSpecValue(newEntry.getValue(), StructDLEntryPos::Abi);
if (abi < newAbi || abi % newAbi != 0)
return false;
@ -609,6 +614,8 @@ LogicalResult LLVMStructType::verifyEntries(DataLayoutEntryListRef entries,
<< "expected layout attribute for " << entry.getKey().get<Type>()
<< " to be a dense integer elements attribute of 1 or 2 elements";
}
if (!values.getElementType().isInteger(64))
return emitError(loc) << "expected i64 entries for " << key;
if (key.isIdentified() || !key.getBody().empty()) {
return emitError(loc) << "unexpected layout attribute for struct " << key;

View File

@ -49,7 +49,8 @@ static Value allocBuffer(ImplicitLocOpBuilder &b,
const LinalgPromotionOptions &options,
Type elementType, Value allocSize, DataLayout &layout,
std::optional<unsigned> alignment = std::nullopt) {
auto width = layout.getTypeSize(elementType);
llvm::TypeSize width = layout.getTypeSize(elementType);
assert(!width.isScalable() && "cannot allocate buffer for a scalable vector");
IntegerAttr alignmentAttr;
if (alignment.has_value())
@ -61,8 +62,8 @@ static Value allocBuffer(ImplicitLocOpBuilder &b,
// Static buffer.
if (std::optional<int64_t> cst = getConstantIntValue(allocSize)) {
auto staticBufferType =
MemRefType::get(width * cst.value(), b.getIntegerType(8));
auto staticBufferType = MemRefType::get(width.getFixedValue() * cst.value(),
b.getIntegerType(8));
staticBufferType =
MemRefType::Builder(staticBufferType).setMemorySpace(memorySpaceAttr);
if (options.useAlloca) {

View File

@ -34,31 +34,31 @@ using namespace mlir;
/// Returns the bitwidth of the index type if specified in the param list.
/// Assumes 64-bit index otherwise.
static unsigned getIndexBitwidth(DataLayoutEntryListRef params) {
static uint64_t getIndexBitwidth(DataLayoutEntryListRef params) {
if (params.empty())
return 64;
auto attr = cast<IntegerAttr>(params.front().getValue());
return attr.getValue().getZExtValue();
}
unsigned
llvm::TypeSize
mlir::detail::getDefaultTypeSize(Type type, const DataLayout &dataLayout,
ArrayRef<DataLayoutEntryInterface> params) {
unsigned bits = getDefaultTypeSizeInBits(type, dataLayout, params);
return llvm::divideCeil(bits, 8);
llvm::TypeSize bits = getDefaultTypeSizeInBits(type, dataLayout, params);
return divideCeil(bits, 8);
}
unsigned mlir::detail::getDefaultTypeSizeInBits(Type type,
const DataLayout &dataLayout,
DataLayoutEntryListRef params) {
llvm::TypeSize
mlir::detail::getDefaultTypeSizeInBits(Type type, const DataLayout &dataLayout,
DataLayoutEntryListRef params) {
if (isa<IntegerType, FloatType>(type))
return type.getIntOrFloatBitWidth();
return llvm::TypeSize::Fixed(type.getIntOrFloatBitWidth());
if (auto ctype = dyn_cast<ComplexType>(type)) {
auto et = ctype.getElementType();
auto innerAlignment =
Type et = ctype.getElementType();
uint64_t innerAlignment =
getDefaultPreferredAlignment(et, dataLayout, params) * 8;
auto innerSize = getDefaultTypeSizeInBits(et, dataLayout, params);
llvm::TypeSize innerSize = getDefaultTypeSizeInBits(et, dataLayout, params);
// Include padding required to align the imaginary value in the complex
// type.
@ -102,35 +102,40 @@ findEntryForIntegerType(IntegerType intType,
return iter->second;
}
static unsigned extractABIAlignment(DataLayoutEntryInterface entry) {
constexpr const static uint64_t kDefaultBitsInByte = 8u;
static uint64_t extractABIAlignment(DataLayoutEntryInterface entry) {
auto values =
cast<DenseIntElementsAttr>(entry.getValue()).getValues<int32_t>();
return *values.begin() / 8u;
cast<DenseIntElementsAttr>(entry.getValue()).getValues<uint64_t>();
return static_cast<uint64_t>(*values.begin()) / kDefaultBitsInByte;
}
static unsigned
static uint64_t
getIntegerTypeABIAlignment(IntegerType intType,
ArrayRef<DataLayoutEntryInterface> params) {
constexpr uint64_t kDefaultSmallIntAlignment = 4u;
constexpr unsigned kSmallIntSize = 64;
if (params.empty()) {
return intType.getWidth() < 64
? llvm::PowerOf2Ceil(llvm::divideCeil(intType.getWidth(), 8))
: 4;
return intType.getWidth() < kSmallIntSize
? llvm::PowerOf2Ceil(
llvm::divideCeil(intType.getWidth(), kDefaultBitsInByte))
: kDefaultSmallIntAlignment;
}
return extractABIAlignment(findEntryForIntegerType(intType, params));
}
static unsigned
static uint64_t
getFloatTypeABIAlignment(FloatType fltType, const DataLayout &dataLayout,
ArrayRef<DataLayoutEntryInterface> params) {
assert(params.size() <= 1 && "at most one data layout entry is expected for "
"the singleton floating-point type");
if (params.empty())
return llvm::PowerOf2Ceil(dataLayout.getTypeSize(fltType));
return llvm::PowerOf2Ceil(dataLayout.getTypeSize(fltType).getFixedValue());
return extractABIAlignment(params[0]);
}
unsigned mlir::detail::getDefaultABIAlignment(
uint64_t mlir::detail::getDefaultABIAlignment(
Type type, const DataLayout &dataLayout,
ArrayRef<DataLayoutEntryInterface> params) {
// Natural alignment is the closest power-of-two number above.
@ -157,23 +162,23 @@ unsigned mlir::detail::getDefaultABIAlignment(
reportMissingDataLayout(type);
}
static unsigned extractPreferredAlignment(DataLayoutEntryInterface entry) {
static uint64_t extractPreferredAlignment(DataLayoutEntryInterface entry) {
auto values =
cast<DenseIntElementsAttr>(entry.getValue()).getValues<int32_t>();
return *std::next(values.begin(), values.size() - 1) / 8u;
cast<DenseIntElementsAttr>(entry.getValue()).getValues<uint64_t>();
return *std::next(values.begin(), values.size() - 1) / kDefaultBitsInByte;
}
static unsigned
static uint64_t
getIntegerTypePreferredAlignment(IntegerType intType,
const DataLayout &dataLayout,
ArrayRef<DataLayoutEntryInterface> params) {
if (params.empty())
return llvm::PowerOf2Ceil(dataLayout.getTypeSize(intType));
return llvm::PowerOf2Ceil(dataLayout.getTypeSize(intType).getFixedValue());
return extractPreferredAlignment(findEntryForIntegerType(intType, params));
}
static unsigned
static uint64_t
getFloatTypePreferredAlignment(FloatType fltType, const DataLayout &dataLayout,
ArrayRef<DataLayoutEntryInterface> params) {
assert(params.size() <= 1 && "at most one data layout entry is expected for "
@ -183,7 +188,7 @@ getFloatTypePreferredAlignment(FloatType fltType, const DataLayout &dataLayout,
return extractPreferredAlignment(params[0]);
}
unsigned mlir::detail::getDefaultPreferredAlignment(
uint64_t mlir::detail::getDefaultPreferredAlignment(
Type type, const DataLayout &dataLayout,
ArrayRef<DataLayoutEntryInterface> params) {
// Preferred alignment is same as natural for floats and vectors.
@ -227,7 +232,7 @@ mlir::detail::getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry) {
// Returns the stack alignment if specified in the given entry. If the entry is
// empty the default alignment zero is returned.
unsigned
uint64_t
mlir::detail::getDefaultStackAlignment(DataLayoutEntryInterface entry) {
if (entry == DataLayoutEntryInterface())
return 0;
@ -353,6 +358,13 @@ LogicalResult mlir::detail::verifyDataLayoutOp(Operation *op) {
return success();
}
llvm::TypeSize mlir::detail::divideCeil(llvm::TypeSize numerator,
uint64_t denominator) {
uint64_t divided =
llvm::divideCeil(numerator.getKnownMinValue(), denominator);
return llvm::TypeSize::get(divided, numerator.isScalable());
}
//===----------------------------------------------------------------------===//
// DataLayout
//===----------------------------------------------------------------------===//
@ -423,8 +435,9 @@ void mlir::DataLayout::checkValid() const {
/// Looks up the value for the given type key in the given cache. If there is no
/// such value in the cache, compute it using the given callback and put it in
/// the cache before returning.
static unsigned cachedLookup(Type t, DenseMap<Type, unsigned> &cache,
function_ref<unsigned(Type)> compute) {
template <typename T>
static T cachedLookup(Type t, DenseMap<Type, T> &cache,
function_ref<T(Type)> compute) {
auto it = cache.find(t);
if (it != cache.end())
return it->second;
@ -433,9 +446,9 @@ static unsigned cachedLookup(Type t, DenseMap<Type, unsigned> &cache,
return result.first->second;
}
unsigned mlir::DataLayout::getTypeSize(Type t) const {
llvm::TypeSize mlir::DataLayout::getTypeSize(Type t) const {
checkValid();
return cachedLookup(t, sizes, [&](Type ty) {
return cachedLookup<llvm::TypeSize>(t, sizes, [&](Type ty) {
DataLayoutEntryList list;
if (originalLayout)
list = originalLayout.getSpecForType(ty.getTypeID());
@ -445,9 +458,9 @@ unsigned mlir::DataLayout::getTypeSize(Type t) const {
});
}
unsigned mlir::DataLayout::getTypeSizeInBits(Type t) const {
llvm::TypeSize mlir::DataLayout::getTypeSizeInBits(Type t) const {
checkValid();
return cachedLookup(t, bitsizes, [&](Type ty) {
return cachedLookup<llvm::TypeSize>(t, bitsizes, [&](Type ty) {
DataLayoutEntryList list;
if (originalLayout)
list = originalLayout.getSpecForType(ty.getTypeID());
@ -457,9 +470,9 @@ unsigned mlir::DataLayout::getTypeSizeInBits(Type t) const {
});
}
unsigned mlir::DataLayout::getTypeABIAlignment(Type t) const {
uint64_t mlir::DataLayout::getTypeABIAlignment(Type t) const {
checkValid();
return cachedLookup(t, abiAlignments, [&](Type ty) {
return cachedLookup<uint64_t>(t, abiAlignments, [&](Type ty) {
DataLayoutEntryList list;
if (originalLayout)
list = originalLayout.getSpecForType(ty.getTypeID());
@ -469,9 +482,9 @@ unsigned mlir::DataLayout::getTypeABIAlignment(Type t) const {
});
}
unsigned mlir::DataLayout::getTypePreferredAlignment(Type t) const {
uint64_t mlir::DataLayout::getTypePreferredAlignment(Type t) const {
checkValid();
return cachedLookup(t, preferredAlignments, [&](Type ty) {
return cachedLookup<uint64_t>(t, preferredAlignments, [&](Type ty) {
DataLayoutEntryList list;
if (originalLayout)
list = originalLayout.getSpecForType(ty.getTypeID());
@ -497,7 +510,7 @@ mlir::Attribute mlir::DataLayout::getAllocaMemorySpace() const {
return *allocaMemorySpace;
}
unsigned mlir::DataLayout::getStackAlignment() const {
uint64_t mlir::DataLayout::getStackAlignment() const {
checkValid();
if (stackAlignment)
return *stackAlignment;
@ -556,14 +569,14 @@ LogicalResult mlir::detail::verifyDataLayoutSpec(DataLayoutSpecInterface spec,
if (isa<IntegerType, FloatType>(sampleType)) {
for (DataLayoutEntryInterface entry : kvp.second) {
auto value = dyn_cast<DenseIntElementsAttr>(entry.getValue());
if (!value || !value.getElementType().isSignlessInteger(32)) {
emitError(loc) << "expected a dense i32 elements attribute in the "
if (!value || !value.getElementType().isSignlessInteger(64)) {
emitError(loc) << "expected a dense i64 elements attribute in the "
"data layout entry "
<< entry;
return failure();
}
auto elements = llvm::to_vector<2>(value.getValues<int32_t>());
auto elements = llvm::to_vector<2>(value.getValues<uint64_t>());
unsigned numElements = elements.size();
if (numElements < 1 || numElements > 2) {
emitError(loc) << "expected 1 or 2 elements in the data layout entry "
@ -571,8 +584,8 @@ LogicalResult mlir::detail::verifyDataLayoutSpec(DataLayoutSpecInterface spec,
return failure();
}
int32_t abi = elements[0];
int32_t preferred = numElements == 2 ? elements[1] : abi;
uint64_t abi = elements[0];
uint64_t preferred = numElements == 2 ? elements[1] : abi;
if (preferred < abi) {
emitError(loc)
<< "preferred alignment is expected to be greater than or equal "

View File

@ -56,21 +56,21 @@ DataLayoutImporter::tryToParseAlphaPrefix(StringRef &token) const {
return prefix;
}
FailureOr<unsigned> DataLayoutImporter::tryToParseInt(StringRef &token) const {
unsigned parameter;
FailureOr<uint64_t> DataLayoutImporter::tryToParseInt(StringRef &token) const {
uint64_t parameter;
if (token.consumeInteger(/*Radix=*/10, parameter))
return failure();
return parameter;
}
FailureOr<SmallVector<unsigned>>
FailureOr<SmallVector<uint64_t>>
DataLayoutImporter::tryToParseIntList(StringRef token) const {
SmallVector<StringRef> tokens;
token.consume_front(":");
token.split(tokens, ':');
// Parse an integer list.
SmallVector<unsigned> results(tokens.size());
SmallVector<uint64_t> results(tokens.size());
for (auto [result, token] : llvm::zip(results, tokens))
if (token.getAsInteger(/*Radix=*/10, result))
return failure();
@ -79,7 +79,7 @@ DataLayoutImporter::tryToParseIntList(StringRef token) const {
FailureOr<DenseIntElementsAttr>
DataLayoutImporter::tryToParseAlignment(StringRef token) const {
FailureOr<SmallVector<unsigned>> alignment = tryToParseIntList(token);
FailureOr<SmallVector<uint64_t>> alignment = tryToParseIntList(token);
if (failed(alignment))
return failure();
if (alignment->empty() || alignment->size() > 2)
@ -89,16 +89,16 @@ DataLayoutImporter::tryToParseAlignment(StringRef token) const {
// form <abi>[:<pref>], where abi specifies the minimal alignment and pref the
// optional preferred alignment. The preferred alignment is set to the minimal
// alignment if not available.
unsigned minimal = (*alignment)[0];
unsigned preferred = alignment->size() == 1 ? minimal : (*alignment)[1];
uint64_t minimal = (*alignment)[0];
uint64_t preferred = alignment->size() == 1 ? minimal : (*alignment)[1];
return DenseIntElementsAttr::get(
VectorType::get({2}, IntegerType::get(context, 32)),
VectorType::get({2}, IntegerType::get(context, 64)),
{minimal, preferred});
}
FailureOr<DenseIntElementsAttr>
DataLayoutImporter::tryToParsePointerAlignment(StringRef token) const {
FailureOr<SmallVector<unsigned>> alignment = tryToParseIntList(token);
FailureOr<SmallVector<uint64_t>> alignment = tryToParseIntList(token);
if (failed(alignment))
return failure();
if (alignment->size() < 2 || alignment->size() > 4)
@ -110,12 +110,12 @@ DataLayoutImporter::tryToParsePointerAlignment(StringRef token) const {
// idx the optional index computation bit width. The preferred alignment is
// set to the minimal alignment if not available and the index computation
// width is set to the pointer size if not available.
unsigned size = (*alignment)[0];
unsigned minimal = (*alignment)[1];
unsigned preferred = alignment->size() < 3 ? minimal : (*alignment)[2];
unsigned idx = alignment->size() < 4 ? size : (*alignment)[3];
return DenseIntElementsAttr::get(
VectorType::get({4}, IntegerType::get(context, 32)),
uint64_t size = (*alignment)[0];
uint64_t minimal = (*alignment)[1];
uint64_t preferred = alignment->size() < 3 ? minimal : (*alignment)[2];
uint64_t idx = alignment->size() < 4 ? size : (*alignment)[3];
return DenseIntElementsAttr::get<uint64_t>(
VectorType::get({4}, IntegerType::get(context, 64)),
{size, minimal, preferred, idx});
}
@ -170,7 +170,7 @@ DataLayoutImporter::tryToEmplaceAllocaAddrSpaceEntry(StringRef token) {
if (keyEntries.count(key))
return success();
FailureOr<unsigned> space = tryToParseInt(token);
FailureOr<uint64_t> space = tryToParseInt(token);
if (failed(space))
return failure();
@ -179,7 +179,10 @@ DataLayoutImporter::tryToEmplaceAllocaAddrSpaceEntry(StringRef token) {
return success();
OpBuilder builder(context);
keyEntries.try_emplace(
key, DataLayoutEntryAttr::get(key, builder.getUI32IntegerAttr(*space)));
key,
DataLayoutEntryAttr::get(
key, builder.getIntegerAttr(
builder.getIntegerType(64, /*isSigned=*/false), *space)));
return success();
}
@ -190,7 +193,7 @@ DataLayoutImporter::tryToEmplaceStackAlignmentEntry(StringRef token) {
if (keyEntries.count(key))
return success();
FailureOr<unsigned> alignment = tryToParseInt(token);
FailureOr<uint64_t> alignment = tryToParseInt(token);
if (failed(alignment))
return failure();
@ -199,7 +202,7 @@ DataLayoutImporter::tryToEmplaceStackAlignmentEntry(StringRef token) {
return success();
OpBuilder builder(context);
keyEntries.try_emplace(key, DataLayoutEntryAttr::get(
key, builder.getI32IntegerAttr(*alignment)));
key, builder.getI64IntegerAttr(*alignment)));
return success();
}
@ -258,7 +261,7 @@ void DataLayoutImporter::translateDataLayout(
}
// Parse integer alignment specifications.
if (*prefix == "i") {
FailureOr<unsigned> width = tryToParseInt(token);
FailureOr<uint64_t> width = tryToParseInt(token);
if (failed(width))
return;
@ -269,7 +272,7 @@ void DataLayoutImporter::translateDataLayout(
}
// Parse float alignment specifications.
if (*prefix == "f") {
FailureOr<unsigned> width = tryToParseInt(token);
FailureOr<uint64_t> width = tryToParseInt(token);
if (failed(width))
return;
@ -280,7 +283,7 @@ void DataLayoutImporter::translateDataLayout(
}
// Parse pointer alignment specifications.
if (*prefix == "p") {
FailureOr<unsigned> space =
FailureOr<uint64_t> space =
token.starts_with(":") ? 0 : tryToParseInt(token);
if (failed(space))
return;

View File

@ -73,10 +73,10 @@ private:
/// Tries to parse an integer parameter and removes the integer from the
/// beginning of the string.
FailureOr<unsigned> tryToParseInt(StringRef &token) const;
FailureOr<uint64_t> tryToParseInt(StringRef &token) const;
/// Tries to parse an integer parameter array.
FailureOr<SmallVector<unsigned>> tryToParseIntList(StringRef token) const;
FailureOr<SmallVector<uint64_t>> tryToParseIntList(StringRef token) const;
/// Tries to parse the parameters of a type alignment entry.
FailureOr<DenseIntElementsAttr> tryToParseAlignment(StringRef token) const;

View File

@ -131,9 +131,9 @@ translateDataLayout(DataLayoutSpecInterface attribute,
} else {
layoutStream << "f";
}
unsigned size = dataLayout.getTypeSizeInBits(type);
unsigned abi = dataLayout.getTypeABIAlignment(type) * 8u;
unsigned preferred =
uint64_t size = dataLayout.getTypeSizeInBits(type);
uint64_t abi = dataLayout.getTypeABIAlignment(type) * 8u;
uint64_t preferred =
dataLayout.getTypePreferredAlignment(type) * 8u;
layoutStream << size << ":" << abi;
if (abi != preferred)
@ -142,12 +142,12 @@ translateDataLayout(DataLayoutSpecInterface attribute,
})
.Case([&](LLVMPointerType ptrType) {
layoutStream << "p" << ptrType.getAddressSpace() << ":";
unsigned size = dataLayout.getTypeSizeInBits(type);
unsigned abi = dataLayout.getTypeABIAlignment(type) * 8u;
unsigned preferred =
uint64_t size = dataLayout.getTypeSizeInBits(type);
uint64_t abi = dataLayout.getTypeABIAlignment(type) * 8u;
uint64_t preferred =
dataLayout.getTypePreferredAlignment(type) * 8u;
layoutStream << size << ":" << abi << ":" << preferred;
if (std::optional<unsigned> index = extractPointerSpecValue(
if (std::optional<uint64_t> index = extractPointerSpecValue(
entry.getValue(), PtrDLEntryPos::Index))
layoutStream << ":" << *index;
return success();
@ -246,15 +246,15 @@ convertDenseElementsAttr(Location loc, DenseElementsAttr denseElementsAttr,
// raw data.
// TODO: we may also need to consider endianness when cross-compiling to an
// architecture where it is different.
unsigned elementByteSize = denseElementsAttr.getRawData().size() /
denseElementsAttr.getNumElements();
int64_t elementByteSize = denseElementsAttr.getRawData().size() /
denseElementsAttr.getNumElements();
if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits())
return nullptr;
// Compute the shape of all dimensions but the innermost. Note that the
// innermost dimension may be that of the vector element type.
bool hasVectorElementType = isa<VectorType>(type.getElementType());
unsigned numAggregates =
int64_t numAggregates =
denseElementsAttr.getNumElements() /
(hasVectorElementType ? 1
: denseElementsAttr.getType().getShape().back());
@ -305,8 +305,8 @@ convertDenseElementsAttr(Location loc, DenseElementsAttr denseElementsAttr,
// Create innermost constants and defer to the default constant creation
// mechanism for other dimensions.
SmallVector<llvm::Constant *> constants;
unsigned aggregateSize = denseElementsAttr.getType().getShape().back() *
(innermostLLVMType->getScalarSizeInBits() / 8);
int64_t aggregateSize = denseElementsAttr.getType().getShape().back() *
(innermostLLVMType->getScalarSizeInBits() / 8);
constants.reserve(numAggregates);
for (unsigned i = 0; i < numAggregates; ++i) {
StringRef data(denseElementsAttr.getRawData().data() + i * aggregateSize,

View File

@ -261,8 +261,8 @@ func.func @mixed_store(%mixed : memref<42x?xf32>, %i : index, %j : index, %val :
// to set address spaces, so the constants below don't reflect the layout
// Update this test once that data layout attribute works how we'd expect it to.
module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<!llvm.ptr, dense<[64, 64, 64]> : vector<3xi32>>,
#dlti.dl_entry<!llvm.ptr<1>, dense<[32, 32, 32]> : vector<3xi32>>> } {
#dlti.dl_entry<!llvm.ptr, dense<[64, 64, 64]> : vector<3xi64>>,
#dlti.dl_entry<!llvm.ptr<1>, dense<[32, 32, 32]> : vector<3xi64>>> } {
// CHECK-LABEL: @memref_memory_space_cast
func.func @memref_memory_space_cast(%input : memref<*xf32>) -> memref<*xf32, 1> {
%cast = memref.memory_space_cast %input : memref<*xf32> to memref<*xf32, 1>

View File

@ -1,6 +1,15 @@
// RUN: mlir-opt %s | FileCheck %s
module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<i1, dense<8> : vector<2xi32>>, #dlti.dl_entry<i8, dense<8> : vector<2xi32>>, #dlti.dl_entry<i16, dense<16> : vector<2xi32>>, #dlti.dl_entry<i32, dense<32> : vector<2xi32>>, #dlti.dl_entry<i64, dense<[32, 64]> : vector<2xi32>>, #dlti.dl_entry<f16, dense<16> : vector<2xi32>>, #dlti.dl_entry<f64, dense<64> : vector<2xi32>>, #dlti.dl_entry<f128, dense<128> : vector<2xi32>>>} {
module attributes {
dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<i1, dense<8> : vector<2xi64>>,
#dlti.dl_entry<i8, dense<8> : vector<2xi64>>,
#dlti.dl_entry<i16, dense<16> : vector<2xi64>>,
#dlti.dl_entry<i32, dense<32> : vector<2xi64>>,
#dlti.dl_entry<i64, dense<[32, 64]> : vector<2xi64>>,
#dlti.dl_entry<f16, dense<16> : vector<2xi64>>,
#dlti.dl_entry<f64, dense<64> : vector<2xi64>>,
#dlti.dl_entry<f128, dense<128> : vector<2xi64>>>} {
// CHECK: llvm.func @foo(%[[ARG0:.+]]: !llvm.ptr, %[[ARG1:.+]]: i32)
llvm.func @foo(%arg0: !llvm.ptr, %arg1: i32) {
// CHECK: %[[C0:.+]] = llvm.mlir.constant(0 : i32)

View File

@ -0,0 +1,14 @@
// RUN: mlir-opt -inline %s | FileCheck %s
// CHECK-LABEL: @byval_2_000_000_000
llvm.func @byval_2_000_000_000(%ptr : !llvm.ptr) {
// CHECK: %[[SIZE:.+]] = llvm.mlir.constant(2000000000 : i64)
// CHECK: "llvm.intr.memcpy"(%{{.*}}, %{{.*}}, %[[SIZE]]
llvm.call @with_byval_arg(%ptr) : (!llvm.ptr) -> ()
llvm.return
}
llvm.func @with_byval_arg(%ptr : !llvm.ptr { llvm.byval = !llvm.array<1000 x array<1000 x array <500 x i32>>> }) {
llvm.return
}

View File

@ -31,11 +31,11 @@ module {
// -----
module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<!llvm.ptr, dense<[32, 32, 64]> : vector<3xi32>>,
#dlti.dl_entry<!llvm.ptr<5>, dense<[64, 64, 64]> : vector<3xi32>>,
#dlti.dl_entry<!llvm.ptr<4>, dense<[32, 64, 64]> : vector<3xi32>>,
#dlti.dl_entry<"dlti.alloca_memory_space", 5 : ui32>,
#dlti.dl_entry<"dlti.stack_alignment", 128 : i32>
#dlti.dl_entry<!llvm.ptr, dense<[32, 32, 64]> : vector<3xi64>>,
#dlti.dl_entry<!llvm.ptr<5>, dense<[64, 64, 64]> : vector<3xi64>>,
#dlti.dl_entry<!llvm.ptr<4>, dense<[32, 64, 64]> : vector<3xi64>>,
#dlti.dl_entry<"dlti.alloca_memory_space", 5 : ui64>,
#dlti.dl_entry<"dlti.stack_alignment", 128 : i64>
>} {
// CHECK: @spec
func.func @spec() {
@ -73,7 +73,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// CHECK: preferred = 8
// CHECK: size = 4
// CHECK: stack_alignment = 128
"test.data_layout_query"() : () -> !llvm.ptr<4>
"test.data_layout_query"() : () -> !llvm.ptr<4>
return
}
}
@ -93,7 +93,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// expected-error@below {{preferred alignment is expected to be at least as large as ABI alignment}}
module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<!llvm.ptr, dense<[64, 64, 32]> : vector<3xi32>>
#dlti.dl_entry<!llvm.ptr, dense<[64, 64, 32]> : vector<3xi64>>
>} {
func.func @pointer() {
return
@ -102,6 +102,14 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// -----
// expected-error @below {{expected i64 parameters for '!llvm.ptr'}}
module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<!llvm.ptr, dense<[32, 32, 64]> : vector<3xi32>>
>} {
}
// -----
module {
// CHECK: @no_spec
func.func @no_spec() {
@ -146,7 +154,7 @@ module {
// -----
module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<!llvm.struct<()>, dense<[32, 32]> : vector<2xi32>>
#dlti.dl_entry<!llvm.struct<()>, dense<[32, 32]> : vector<2xi64>>
>} {
// CHECK: @spec
func.func @spec() {
@ -184,7 +192,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// -----
module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<!llvm.struct<()>, dense<[32]> : vector<1xi32>>
#dlti.dl_entry<!llvm.struct<()>, dense<[32]> : vector<1xi64>>
>} {
// CHECK: @spec_without_preferred
func.func @spec_without_preferred() {
@ -202,7 +210,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// expected-error@below {{unexpected layout attribute for struct '!llvm.struct<(i8)>'}}
module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<!llvm.struct<(i8)>, dense<[64, 64]> : vector<2xi32>>
#dlti.dl_entry<!llvm.struct<(i8)>, dense<[64, 64]> : vector<2xi64>>
>} {
func.func @struct() {
return
@ -213,7 +221,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// expected-error@below {{expected layout attribute for '!llvm.struct<()>' to be a dense integer elements attribute of 1 or 2 elements}}
module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<!llvm.struct<()>, dense<[64, 64, 64]> : vector<3xi32>>
#dlti.dl_entry<!llvm.struct<()>, dense<[64, 64, 64]> : vector<3xi64>>
>} {
func.func @struct() {
return
@ -224,7 +232,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// expected-error@below {{preferred alignment is expected to be at least as large as ABI alignment}}
module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<!llvm.struct<()>, dense<[64, 32]> : vector<2xi32>>
#dlti.dl_entry<!llvm.struct<()>, dense<[64, 32]> : vector<2xi64>>
>} {
func.func @struct() {
return
@ -263,7 +271,7 @@ module {
// -----
module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<!llvm.struct<()>, dense<[64]> : vector<1xi32>>
#dlti.dl_entry<!llvm.struct<()>, dense<[64]> : vector<1xi64>>
>} {
// CHECK: @overaligned
func.func @overaligned() {
@ -276,3 +284,11 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
return
}
}
// -----
// expected-error @below {{expected i64 entries for '!llvm.struct<()>'}}
module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<!llvm.struct<()>, dense<[64]> : vector<1xi32>>
>} {
}

View File

@ -216,8 +216,8 @@ func.func @integers() {
"test.data_layout_query"() : () -> i128
"test.maybe_terminator"() : () -> ()
}) { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<i32, dense<64> : vector<1xi32>>,
#dlti.dl_entry<i64, dense<128> : vector<1xi32>>
#dlti.dl_entry<i32, dense<64> : vector<1xi64>>,
#dlti.dl_entry<i64, dense<128> : vector<1xi64>>
>} : () -> ()
"test.op_with_data_layout"() ({
// CHECK: alignment = 8
@ -238,8 +238,8 @@ func.func @integers() {
"test.data_layout_query"() : () -> i128
"test.maybe_terminator"() : () -> ()
}) { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<i32, dense<[64, 128]> : vector<2xi32>>,
#dlti.dl_entry<i64, dense<[128, 256]> : vector<2xi32>>
#dlti.dl_entry<i32, dense<[64, 128]> : vector<2xi64>>,
#dlti.dl_entry<i64, dense<[128, 256]> : vector<2xi64>>
>} : () -> ()
return
}
@ -256,8 +256,8 @@ func.func @floats() {
"test.data_layout_query"() : () -> f80
"test.maybe_terminator"() : () -> ()
}) { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<f32, dense<64> : vector<1xi32>>,
#dlti.dl_entry<f80, dense<128> : vector<1xi32>>
#dlti.dl_entry<f32, dense<64> : vector<1xi64>>,
#dlti.dl_entry<f80, dense<128> : vector<1xi64>>
>} : () -> ()
"test.op_with_data_layout"() ({
// CHECK: alignment = 8
@ -270,8 +270,8 @@ func.func @floats() {
"test.data_layout_query"() : () -> f80
"test.maybe_terminator"() : () -> ()
}) { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<f32, dense<[64, 128]> : vector<2xi32>>,
#dlti.dl_entry<f80, dense<[128, 256]> : vector<2xi32>>
#dlti.dl_entry<f32, dense<[64, 128]> : vector<2xi64>>,
#dlti.dl_entry<f80, dense<[128, 256]> : vector<2xi64>>
>} : () -> ()
return
}

View File

@ -7,23 +7,23 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// -----
// expected-error@below {{expected a dense i32 elements attribute}}
// expected-error@below {{expected a dense i64 elements attribute}}
module attributes {dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<i32, dense<[64,128]> : vector<2xi64>>>
#dlti.dl_entry<i32, dense<[64,128]> : vector<2xi32>>>
} {}
// -----
// expected-error@below {{expected 1 or 2 elements}}
module attributes {dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<i32, dense<[64,64,64]> : vector<3xi32>>>
#dlti.dl_entry<i32, dense<[64,64,64]> : vector<3xi64>>>
} {}
// -----
// expected-error@below {{preferred alignment is expected to be greater than or equal to the abi alignment}}
module attributes {dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<i32, dense<[64,32]> : vector<2xi32>>>
#dlti.dl_entry<i32, dense<[64,32]> : vector<2xi64>>>
} {}
// -----

View File

@ -5,15 +5,15 @@
; CHECK: dlti.dl_spec =
; CHECK: #dlti.dl_spec<
; CHECK-DAG: #dlti.dl_entry<"dlti.endianness", "little">
; CHECK-DAG: #dlti.dl_entry<i1, dense<8> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<i8, dense<8> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<i16, dense<16> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<i32, dense<32> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<i64, dense<[32, 64]> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr, dense<64> : vector<4xi32>>
; CHECK-DAG: #dlti.dl_entry<f16, dense<16> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<f64, dense<64> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<f128, dense<128> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<i1, dense<8> : vector<2xi64>>
; CHECK-DAG: #dlti.dl_entry<i8, dense<8> : vector<2xi64>>
; CHECK-DAG: #dlti.dl_entry<i16, dense<16> : vector<2xi64>>
; CHECK-DAG: #dlti.dl_entry<i32, dense<32> : vector<2xi64>>
; CHECK-DAG: #dlti.dl_entry<i64, dense<[32, 64]> : vector<2xi64>>
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr, dense<64> : vector<4xi64>>
; CHECK-DAG: #dlti.dl_entry<f16, dense<16> : vector<2xi64>>
; CHECK-DAG: #dlti.dl_entry<f64, dense<64> : vector<2xi64>>
; CHECK-DAG: #dlti.dl_entry<f128, dense<128> : vector<2xi64>>
; CHECK: >
target datalayout = ""
@ -22,13 +22,13 @@ target datalayout = ""
; CHECK: dlti.dl_spec =
; CHECK: #dlti.dl_spec<
; CHECK-DAG: #dlti.dl_entry<"dlti.endianness", "little">
; CHECK-DAG: #dlti.dl_entry<i64, dense<64> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<f80, dense<128> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<i8, dense<8> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr<270>, dense<[32, 64, 64, 32]> : vector<4xi32>>
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr<271>, dense<32> : vector<4xi32>>
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr<272>, dense<64> : vector<4xi32>>
; CHECK-DAG: #dlti.dl_entry<"dlti.stack_alignment", 128 : i32>
; CHECK-DAG: #dlti.dl_entry<i64, dense<64> : vector<2xi64>>
; CHECK-DAG: #dlti.dl_entry<f80, dense<128> : vector<2xi64>>
; CHECK-DAG: #dlti.dl_entry<i8, dense<8> : vector<2xi64>>
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr<270>, dense<[32, 64, 64, 32]> : vector<4xi64>>
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr<271>, dense<32> : vector<4xi64>>
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr<272>, dense<64> : vector<4xi64>>
; CHECK-DAG: #dlti.dl_entry<"dlti.stack_alignment", 128 : i64>
target datalayout = "e-m:e-p270:32:64-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
; // -----
@ -36,10 +36,10 @@ target datalayout = "e-m:e-p270:32:64-p271:32:32-p272:64:64-i64:64-f80:128-n8:16
; CHECK: dlti.dl_spec =
; CHECK: #dlti.dl_spec<
; CHECK-DAG: #dlti.dl_entry<"dlti.endianness", "big">
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr<270>, dense<[16, 32, 64, 8]> : vector<4xi32>>
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr<271>, dense<[16, 32, 64, 16]> : vector<4xi32>>
; CHECK-DAG: #dlti.dl_entry<"dlti.alloca_memory_space", 1 : ui32>
; CHECK-DAG: #dlti.dl_entry<i64, dense<[64, 128]> : vector<2xi32>>
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr<270>, dense<[16, 32, 64, 8]> : vector<4xi64>>
; CHECK-DAG: #dlti.dl_entry<!llvm.ptr<271>, dense<[16, 32, 64, 16]> : vector<4xi64>>
; CHECK-DAG: #dlti.dl_entry<"dlti.alloca_memory_space", 1 : ui64>
; CHECK-DAG: #dlti.dl_entry<i64, dense<[64, 128]> : vector<2xi64>>
target datalayout = "A1-E-p270:16:32:64:8-p271:16:32:64-i64:64:128"
; // -----

View File

@ -13,10 +13,10 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<"dlti.alloca_memory_space", 4 : ui32>,
#dlti.dl_entry<"dlti.stack_alignment", 128 : i32>,
#dlti.dl_entry<index, 64>,
#dlti.dl_entry<i64, dense<[64,128]> : vector<2xi32>>,
#dlti.dl_entry<f80, dense<[128,256]> : vector<2xi32>>,
#dlti.dl_entry<!llvm.ptr, dense<[32,64,128]> : vector<3xi32>>,
#dlti.dl_entry<!llvm.ptr<1>, dense<[32,32,32,16]> : vector<4xi32>>
#dlti.dl_entry<i64, dense<[64,128]> : vector<2xi64>>,
#dlti.dl_entry<f80, dense<[128,256]> : vector<2xi64>>,
#dlti.dl_entry<!llvm.ptr, dense<[32,64,128]> : vector<3xi64>>,
#dlti.dl_entry<!llvm.ptr<1>, dense<[32,32,32,16]> : vector<4xi64>>
>} {
llvm.func @foo() {
llvm.return
@ -43,19 +43,19 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<
// expected-error@below {{unsupported data layout for non-signless integer 'ui64'}}
module attributes {dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<ui64, dense<[64,128]> : vector<2xi32>>>
#dlti.dl_entry<ui64, dense<[64,128]> : vector<2xi64>>>
} {}
// -----
// expected-error@below {{unsupported type in data layout: 'bf16'}}
module attributes {dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<bf16, dense<[64,128]> : vector<2xi32>>>
#dlti.dl_entry<bf16, dense<[64,128]> : vector<2xi64>>>
} {}
// -----
// expected-error@below {{unsupported data layout key "foo"}}
module attributes {dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<"foo", dense<[64,128]> : vector<2xi32>>>
#dlti.dl_entry<"foo", dense<[64,128]> : vector<2xi64>>>
} {}

View File

@ -157,7 +157,7 @@ def TestTypeWithLayoutType : Test_Type<"TestTypeWithLayout", [
::mlir::Location loc) const;
private:
unsigned extractKind(::mlir::DataLayoutEntryListRef params,
uint64_t extractKind(::mlir::DataLayoutEntryListRef params,
::llvm::StringRef expectedKind) const;
public:

View File

@ -21,6 +21,7 @@
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/TypeSize.h"
#include <optional>
using namespace mlir;
@ -258,19 +259,19 @@ void TestTypeWithLayoutType::print(AsmPrinter &printer) const {
printer << "<" << getKey() << ">";
}
unsigned
llvm::TypeSize
TestTypeWithLayoutType::getTypeSizeInBits(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
return extractKind(params, "size");
return llvm::TypeSize::Fixed(extractKind(params, "size"));
}
unsigned
uint64_t
TestTypeWithLayoutType::getABIAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const {
return extractKind(params, "alignment");
}
unsigned TestTypeWithLayoutType::getPreferredAlignment(
uint64_t TestTypeWithLayoutType::getPreferredAlignment(
const DataLayout &dataLayout, DataLayoutEntryListRef params) const {
return extractKind(params, "preferred");
}
@ -303,7 +304,7 @@ TestTypeWithLayoutType::verifyEntries(DataLayoutEntryListRef params,
return success();
}
unsigned TestTypeWithLayoutType::extractKind(DataLayoutEntryListRef params,
uint64_t TestTypeWithLayoutType::extractKind(DataLayoutEntryListRef params,
StringRef expectedKind) const {
for (DataLayoutEntryInterface entry : params) {
ArrayRef<Attribute> pair =

View File

@ -85,17 +85,17 @@ struct SingleQueryType
static SingleQueryType get(MLIRContext *ctx) { return Base::get(ctx); }
unsigned getTypeSizeInBits(const DataLayout &layout,
DataLayoutEntryListRef params) const {
llvm::TypeSize getTypeSizeInBits(const DataLayout &layout,
DataLayoutEntryListRef params) const {
static bool executed = false;
if (executed)
llvm::report_fatal_error("repeated call");
executed = true;
return 1;
return llvm::TypeSize::Fixed(1);
}
unsigned getABIAlignment(const DataLayout &layout,
uint64_t getABIAlignment(const DataLayout &layout,
DataLayoutEntryListRef params) {
static bool executed = false;
if (executed)
@ -105,7 +105,7 @@ struct SingleQueryType
return 2;
}
unsigned getPreferredAlignment(const DataLayout &layout,
uint64_t getPreferredAlignment(const DataLayout &layout,
DataLayoutEntryListRef params) {
static bool executed = false;
if (executed)
@ -149,8 +149,9 @@ struct OpWithLayout : public Op<OpWithLayout, DataLayoutOpInterface::Trait> {
return getOperation()->getAttrOfType<DataLayoutSpecInterface>(kAttrName);
}
static unsigned getTypeSizeInBits(Type type, const DataLayout &dataLayout,
DataLayoutEntryListRef params) {
static llvm::TypeSize getTypeSizeInBits(Type type,
const DataLayout &dataLayout,
DataLayoutEntryListRef params) {
// Make a recursive query.
if (isa<FloatType>(type))
return dataLayout.getTypeSizeInBits(
@ -160,21 +161,22 @@ struct OpWithLayout : public Op<OpWithLayout, DataLayoutOpInterface::Trait> {
if (auto iType = dyn_cast<IntegerType>(type)) {
for (DataLayoutEntryInterface entry : params)
if (llvm::dyn_cast_if_present<Type>(entry.getKey()) == type)
return 8 *
cast<IntegerAttr>(entry.getValue()).getValue().getZExtValue();
return 8 * iType.getIntOrFloatBitWidth();
return llvm::TypeSize::Fixed(
8 *
cast<IntegerAttr>(entry.getValue()).getValue().getZExtValue());
return llvm::TypeSize::Fixed(8 * iType.getIntOrFloatBitWidth());
}
// Use the default process for everything else.
return detail::getDefaultTypeSize(type, dataLayout, params);
}
static unsigned getTypeABIAlignment(Type type, const DataLayout &dataLayout,
static uint64_t getTypeABIAlignment(Type type, const DataLayout &dataLayout,
DataLayoutEntryListRef params) {
return llvm::PowerOf2Ceil(getTypeSize(type, dataLayout, params));
}
static unsigned getTypePreferredAlignment(Type type,
static uint64_t getTypePreferredAlignment(Type type,
const DataLayout &dataLayout,
DataLayoutEntryListRef params) {
return 2 * getTypeABIAlignment(type, dataLayout, params);
@ -195,9 +197,9 @@ struct OpWith7BitByte
}
// Bytes are assumed to be 7-bit here.
static unsigned getTypeSize(Type type, const DataLayout &dataLayout,
DataLayoutEntryListRef params) {
return llvm::divideCeil(dataLayout.getTypeSizeInBits(type), 7);
static llvm::TypeSize getTypeSize(Type type, const DataLayout &dataLayout,
DataLayoutEntryListRef params) {
return mlir::detail::divideCeil(dataLayout.getTypeSizeInBits(type), 7);
}
};