diff --git a/mlir/docs/DataLayout.md b/mlir/docs/DataLayout.md index e246e66c7fe227..b9dde30519d6ed 100644 --- a/mlir/docs/DataLayout.md +++ b/mlir/docs/DataLayout.md @@ -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; }; ``` diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h index ba2f14f173aa0c..06a41c7c1a7245 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h @@ -186,13 +186,13 @@ class LLVMStructType /// 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 extractPointerSpecValue(Attribute attr, +std::optional extractPointerSpecValue(Attribute attr, PtrDLEntryPos pos); } // namespace LLVM diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h index e6e31d171c6a9f..f4b9b95fb89f89 100644 --- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h +++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h @@ -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 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 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 @@ class DataLayout { 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 @@ class DataLayout { /// 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 @@ class DataLayout { Operation *scope; /// Caches for individual requests. - mutable DenseMap sizes; - mutable DenseMap bitsizes; - mutable DenseMap abiAlignments; - mutable DenseMap preferredAlignments; + mutable DenseMap sizes; + mutable DenseMap bitsizes; + mutable DenseMap abiAlignments; + mutable DenseMap preferredAlignments; /// Cache for alloca memory space. mutable std::optional allocaMemorySpace; /// Cache for stack alignment. - mutable std::optional stackAlignment; + mutable std::optional stackAlignment; }; } // namespace mlir diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td index bac8c23ceec01a..2f60a16baf50bc 100644 --- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td +++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td @@ -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) diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp index 8841aa8362569a..f4aa939791588d 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp @@ -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 @@ -178,24 +178,25 @@ LLVMArrayType::verify(function_ref 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 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 mlir::LLVM::extractPointerSpecValue(Attribute attr, +std::optional mlir::LLVM::extractPointerSpecValue(Attribute attr, PtrDLEntryPos pos) { - auto spec = llvm::cast(attr); - auto idx = static_cast(pos); + auto spec = cast(attr); + auto idx = static_cast(pos); if (idx >= spec.size()) return std::nullopt; - return spec.getValues()[idx]; + return spec.getValues()[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 +static std::optional 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(entry.getKey().get()) - .getAddressSpace() == type.getAddressSpace()) { + if (cast(entry.getKey().get()).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 size = + if (std::optional 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 alignment = + if (std::optional 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 alignment = + if (std::optional 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(newEntry.getKey().get()); const auto *it = llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) { @@ -360,8 +361,8 @@ bool LLVMPointerType::areCompatible(DataLayoutEntryListRef oldLayout, } Attribute newSpec = llvm::cast(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(); auto values = llvm::dyn_cast(entry.getValue()); if (!values || (values.size() != 3 && values.size() != 4)) { return emitError(loc) - << "expected layout attribute for " << entry.getKey().get() + << "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 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 +static std::optional getStructDataLayoutEntry(DataLayoutEntryListRef params, LLVMStructType type, StructDLEntryPos pos) { const auto *currentEntry = @@ -523,14 +528,14 @@ getStructDataLayoutEntry(DataLayoutEntryListRef params, LLVMStructType type, auto attr = llvm::cast(currentEntry->getValue()); if (pos == StructDLEntryPos::Preferred && - attr.size() <= static_cast(StructDLEntryPos::Preferred)) + attr.size() <= static_cast(StructDLEntryPos::Preferred)) // If no preferred was specified, fall back to abi alignment pos = StructDLEntryPos::Abi; - return attr.getValues()[static_cast(pos)]; + return attr.getValues()[static_cast(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 entryResult = + if (std::optional 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(attr) - .getValues()[static_cast(pos)]; + .getValues()[static_cast(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() << " 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; diff --git a/mlir/lib/Dialect/Linalg/Transforms/Promotion.cpp b/mlir/lib/Dialect/Linalg/Transforms/Promotion.cpp index 5c140a7d692a93..7c8ee1727d56f8 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/Promotion.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Promotion.cpp @@ -49,7 +49,8 @@ static Value allocBuffer(ImplicitLocOpBuilder &b, const LinalgPromotionOptions &options, Type elementType, Value allocSize, DataLayout &layout, std::optional 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 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) { diff --git a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp index 8edd89f5d3a312..dda011e95de3ae 100644 --- a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp +++ b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp @@ -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(params.front().getValue()); return attr.getValue().getZExtValue(); } -unsigned +llvm::TypeSize mlir::detail::getDefaultTypeSize(Type type, const DataLayout &dataLayout, ArrayRef 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(type)) - return type.getIntOrFloatBitWidth(); + return llvm::TypeSize::Fixed(type.getIntOrFloatBitWidth()); if (auto ctype = dyn_cast(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(entry.getValue()).getValues(); - return *values.begin() / 8u; + cast(entry.getValue()).getValues(); + return static_cast(*values.begin()) / kDefaultBitsInByte; } -static unsigned +static uint64_t getIntegerTypeABIAlignment(IntegerType intType, ArrayRef 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 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 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(entry.getValue()).getValues(); - return *std::next(values.begin(), values.size() - 1) / 8u; + cast(entry.getValue()).getValues(); + return *std::next(values.begin(), values.size() - 1) / kDefaultBitsInByte; } -static unsigned +static uint64_t getIntegerTypePreferredAlignment(IntegerType intType, const DataLayout &dataLayout, ArrayRef 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 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 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 &cache, - function_ref compute) { +template +static T cachedLookup(Type t, DenseMap &cache, + function_ref compute) { auto it = cache.find(t); if (it != cache.end()) return it->second; @@ -433,9 +446,9 @@ static unsigned cachedLookup(Type t, DenseMap &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(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(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(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(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(sampleType)) { for (DataLayoutEntryInterface entry : kvp.second) { auto value = dyn_cast(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()); + auto elements = llvm::to_vector<2>(value.getValues()); 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 " diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp index d19590600bb9a2..95f3cc074b1ddf 100644 --- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp +++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp @@ -56,21 +56,21 @@ DataLayoutImporter::tryToParseAlphaPrefix(StringRef &token) const { return prefix; } -FailureOr DataLayoutImporter::tryToParseInt(StringRef &token) const { - unsigned parameter; +FailureOr DataLayoutImporter::tryToParseInt(StringRef &token) const { + uint64_t parameter; if (token.consumeInteger(/*Radix=*/10, parameter)) return failure(); return parameter; } -FailureOr> +FailureOr> DataLayoutImporter::tryToParseIntList(StringRef token) const { SmallVector tokens; token.consume_front(":"); token.split(tokens, ':'); // Parse an integer list. - SmallVector results(tokens.size()); + SmallVector 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 DataLayoutImporter::tryToParseAlignment(StringRef token) const { - FailureOr> alignment = tryToParseIntList(token); + FailureOr> alignment = tryToParseIntList(token); if (failed(alignment)) return failure(); if (alignment->empty() || alignment->size() > 2) @@ -89,16 +89,16 @@ DataLayoutImporter::tryToParseAlignment(StringRef token) const { // form [:], 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 DataLayoutImporter::tryToParsePointerAlignment(StringRef token) const { - FailureOr> alignment = tryToParseIntList(token); + FailureOr> 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( + 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 space = tryToParseInt(token); + FailureOr 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 alignment = tryToParseInt(token); + FailureOr 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 width = tryToParseInt(token); + FailureOr width = tryToParseInt(token); if (failed(width)) return; @@ -269,7 +272,7 @@ void DataLayoutImporter::translateDataLayout( } // Parse float alignment specifications. if (*prefix == "f") { - FailureOr width = tryToParseInt(token); + FailureOr width = tryToParseInt(token); if (failed(width)) return; @@ -280,7 +283,7 @@ void DataLayoutImporter::translateDataLayout( } // Parse pointer alignment specifications. if (*prefix == "p") { - FailureOr space = + FailureOr space = token.starts_with(":") ? 0 : tryToParseInt(token); if (failed(space)) return; diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h b/mlir/lib/Target/LLVMIR/DataLayoutImporter.h index 5c1606216037ed..15f0f7ddf07059 100644 --- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h +++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.h @@ -73,10 +73,10 @@ class DataLayoutImporter { /// Tries to parse an integer parameter and removes the integer from the /// beginning of the string. - FailureOr tryToParseInt(StringRef &token) const; + FailureOr tryToParseInt(StringRef &token) const; /// Tries to parse an integer parameter array. - FailureOr> tryToParseIntList(StringRef token) const; + FailureOr> tryToParseIntList(StringRef token) const; /// Tries to parse the parameters of a type alignment entry. FailureOr tryToParseAlignment(StringRef token) const; diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index 911c7141e45d5f..ef1c8c21d54b08 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -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 index = extractPointerSpecValue( + if (std::optional 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(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 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, diff --git a/mlir/test/Conversion/MemRefToLLVM/convert-dynamic-memref-ops.mlir b/mlir/test/Conversion/MemRefToLLVM/convert-dynamic-memref-ops.mlir index 66dc30127ae741..609fcb10b992c6 100644 --- a/mlir/test/Conversion/MemRefToLLVM/convert-dynamic-memref-ops.mlir +++ b/mlir/test/Conversion/MemRefToLLVM/convert-dynamic-memref-ops.mlir @@ -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 : vector<3xi32>>, - #dlti.dl_entry, dense<[32, 32, 32]> : vector<3xi32>>> } { + #dlti.dl_entry : vector<3xi64>>, + #dlti.dl_entry, 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> diff --git a/mlir/test/Dialect/LLVMIR/dynamic-gep-index.mlir b/mlir/test/Dialect/LLVMIR/dynamic-gep-index.mlir index f5808134ea026b..be0ce2f068284e 100644 --- a/mlir/test/Dialect/LLVMIR/dynamic-gep-index.mlir +++ b/mlir/test/Dialect/LLVMIR/dynamic-gep-index.mlir @@ -1,6 +1,15 @@ // RUN: mlir-opt %s | FileCheck %s -module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>>} { +module attributes { + dlti.dl_spec = #dlti.dl_spec< + #dlti.dl_entry : vector<2xi64>>, + #dlti.dl_entry : vector<2xi64>>, + #dlti.dl_entry : vector<2xi64>>, + #dlti.dl_entry : vector<2xi64>>, + #dlti.dl_entry : vector<2xi64>>, + #dlti.dl_entry : vector<2xi64>>, + #dlti.dl_entry : vector<2xi64>>, + #dlti.dl_entry : 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) diff --git a/mlir/test/Dialect/LLVMIR/inline-byval-huge.mlir b/mlir/test/Dialect/LLVMIR/inline-byval-huge.mlir new file mode 100644 index 00000000000000..3e246d7f21d5f8 --- /dev/null +++ b/mlir/test/Dialect/LLVMIR/inline-byval-huge.mlir @@ -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 +} diff --git a/mlir/test/Dialect/LLVMIR/layout.mlir b/mlir/test/Dialect/LLVMIR/layout.mlir index 363222b5ad912e..99d61785384487 100644 --- a/mlir/test/Dialect/LLVMIR/layout.mlir +++ b/mlir/test/Dialect/LLVMIR/layout.mlir @@ -31,11 +31,11 @@ module { // ----- module attributes { dlti.dl_spec = #dlti.dl_spec< - #dlti.dl_entry : vector<3xi32>>, - #dlti.dl_entry, dense<[64, 64, 64]> : vector<3xi32>>, - #dlti.dl_entry, 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 : vector<3xi64>>, + #dlti.dl_entry, dense<[64, 64, 64]> : vector<3xi64>>, + #dlti.dl_entry, 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 : vector<3xi32>> + #dlti.dl_entry : 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 : 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, dense<[32, 32]> : vector<2xi32>> + #dlti.dl_entry, 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, dense<[32]> : vector<1xi32>> + #dlti.dl_entry, 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, dense<[64, 64]> : vector<2xi32>> + #dlti.dl_entry, 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, dense<[64, 64, 64]> : vector<3xi32>> + #dlti.dl_entry, 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, dense<[64, 32]> : vector<2xi32>> + #dlti.dl_entry, 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, dense<[64]> : vector<1xi32>> + #dlti.dl_entry, 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, dense<[64]> : vector<1xi32>> +>} { +} diff --git a/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir b/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir index 816cc0686d51d4..9f9240ac6f8cea 100644 --- a/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir +++ b/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir @@ -216,8 +216,8 @@ func.func @integers() { "test.data_layout_query"() : () -> i128 "test.maybe_terminator"() : () -> () }) { dlti.dl_spec = #dlti.dl_spec< - #dlti.dl_entry : vector<1xi32>>, - #dlti.dl_entry : vector<1xi32>> + #dlti.dl_entry : vector<1xi64>>, + #dlti.dl_entry : 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 : vector<2xi32>>, - #dlti.dl_entry : vector<2xi32>> + #dlti.dl_entry : vector<2xi64>>, + #dlti.dl_entry : 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 : vector<1xi32>>, - #dlti.dl_entry : vector<1xi32>> + #dlti.dl_entry : vector<1xi64>>, + #dlti.dl_entry : 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 : vector<2xi32>>, - #dlti.dl_entry : vector<2xi32>> + #dlti.dl_entry : vector<2xi64>>, + #dlti.dl_entry : vector<2xi64>> >} : () -> () return } diff --git a/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir b/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir index e45ec816fcbf79..55bb1d2eac911c 100644 --- a/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir +++ b/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir @@ -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 : vector<2xi64>>> +#dlti.dl_entry : vector<2xi32>>> } {} // ----- // expected-error@below {{expected 1 or 2 elements}} module attributes {dlti.dl_spec = #dlti.dl_spec< -#dlti.dl_entry : vector<3xi32>>> +#dlti.dl_entry : 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 : vector<2xi32>>> +#dlti.dl_entry : vector<2xi64>>> } {} // ----- diff --git a/mlir/test/Target/LLVMIR/Import/data-layout.ll b/mlir/test/Target/LLVMIR/Import/data-layout.ll index 4336f0dbbc4a91..de90ac1e271140 100644 --- a/mlir/test/Target/LLVMIR/Import/data-layout.ll +++ b/mlir/test/Target/LLVMIR/Import/data-layout.ll @@ -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 : vector<2xi32>> -; CHECK-DAG: #dlti.dl_entry : vector<2xi32>> -; CHECK-DAG: #dlti.dl_entry : vector<2xi32>> -; CHECK-DAG: #dlti.dl_entry : vector<2xi32>> -; CHECK-DAG: #dlti.dl_entry : vector<2xi32>> -; CHECK-DAG: #dlti.dl_entry : vector<4xi32>> -; CHECK-DAG: #dlti.dl_entry : vector<2xi32>> -; CHECK-DAG: #dlti.dl_entry : vector<2xi32>> -; CHECK-DAG: #dlti.dl_entry : vector<2xi32>> +; CHECK-DAG: #dlti.dl_entry : vector<2xi64>> +; CHECK-DAG: #dlti.dl_entry : vector<2xi64>> +; CHECK-DAG: #dlti.dl_entry : vector<2xi64>> +; CHECK-DAG: #dlti.dl_entry : vector<2xi64>> +; CHECK-DAG: #dlti.dl_entry : vector<2xi64>> +; CHECK-DAG: #dlti.dl_entry : vector<4xi64>> +; CHECK-DAG: #dlti.dl_entry : vector<2xi64>> +; CHECK-DAG: #dlti.dl_entry : vector<2xi64>> +; CHECK-DAG: #dlti.dl_entry : 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 : vector<2xi32>> -; CHECK-DAG: #dlti.dl_entry : vector<2xi32>> -; CHECK-DAG: #dlti.dl_entry : vector<2xi32>> -; CHECK-DAG: #dlti.dl_entry, dense<[32, 64, 64, 32]> : vector<4xi32>> -; CHECK-DAG: #dlti.dl_entry, dense<32> : vector<4xi32>> -; CHECK-DAG: #dlti.dl_entry, dense<64> : vector<4xi32>> -; CHECK-DAG: #dlti.dl_entry<"dlti.stack_alignment", 128 : i32> +; CHECK-DAG: #dlti.dl_entry : vector<2xi64>> +; CHECK-DAG: #dlti.dl_entry : vector<2xi64>> +; CHECK-DAG: #dlti.dl_entry : vector<2xi64>> +; CHECK-DAG: #dlti.dl_entry, dense<[32, 64, 64, 32]> : vector<4xi64>> +; CHECK-DAG: #dlti.dl_entry, dense<32> : vector<4xi64>> +; CHECK-DAG: #dlti.dl_entry, 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, dense<[16, 32, 64, 8]> : vector<4xi32>> -; CHECK-DAG: #dlti.dl_entry, dense<[16, 32, 64, 16]> : vector<4xi32>> -; CHECK-DAG: #dlti.dl_entry<"dlti.alloca_memory_space", 1 : ui32> -; CHECK-DAG: #dlti.dl_entry : vector<2xi32>> +; CHECK-DAG: #dlti.dl_entry, dense<[16, 32, 64, 8]> : vector<4xi64>> +; CHECK-DAG: #dlti.dl_entry, dense<[16, 32, 64, 16]> : vector<4xi64>> +; CHECK-DAG: #dlti.dl_entry<"dlti.alloca_memory_space", 1 : ui64> +; CHECK-DAG: #dlti.dl_entry : vector<2xi64>> target datalayout = "A1-E-p270:16:32:64:8-p271:16:32:64-i64:64:128" ; // ----- diff --git a/mlir/test/Target/LLVMIR/data-layout.mlir b/mlir/test/Target/LLVMIR/data-layout.mlir index f1304e12c303d4..e61972a0dd9764 100644 --- a/mlir/test/Target/LLVMIR/data-layout.mlir +++ b/mlir/test/Target/LLVMIR/data-layout.mlir @@ -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, -#dlti.dl_entry : vector<2xi32>>, -#dlti.dl_entry : vector<2xi32>>, -#dlti.dl_entry : vector<3xi32>>, -#dlti.dl_entry, dense<[32,32,32,16]> : vector<4xi32>> +#dlti.dl_entry : vector<2xi64>>, +#dlti.dl_entry : vector<2xi64>>, +#dlti.dl_entry : vector<3xi64>>, +#dlti.dl_entry, 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 : vector<2xi32>>> +#dlti.dl_entry : vector<2xi64>>> } {} // ----- // expected-error@below {{unsupported type in data layout: 'bf16'}} module attributes {dlti.dl_spec = #dlti.dl_spec< -#dlti.dl_entry : vector<2xi32>>> +#dlti.dl_entry : 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>>> } {} diff --git a/mlir/test/lib/Dialect/Test/TestTypeDefs.td b/mlir/test/lib/Dialect/Test/TestTypeDefs.td index 2a8bdad8fb25d9..1957845c842f20 100644 --- a/mlir/test/lib/Dialect/Test/TestTypeDefs.td +++ b/mlir/test/lib/Dialect/Test/TestTypeDefs.td @@ -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: diff --git a/mlir/test/lib/Dialect/Test/TestTypes.cpp b/mlir/test/lib/Dialect/Test/TestTypes.cpp index abb35d71d7f6d5..cb7ef7f1749999 100644 --- a/mlir/test/lib/Dialect/Test/TestTypes.cpp +++ b/mlir/test/lib/Dialect/Test/TestTypes.cpp @@ -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 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 pair = diff --git a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp index dcb7d9684bb358..a27b95ca4614b0 100644 --- a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp +++ b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp @@ -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 { return getOperation()->getAttrOfType(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(type)) return dataLayout.getTypeSizeInBits( @@ -160,21 +161,22 @@ struct OpWithLayout : public Op { if (auto iType = dyn_cast(type)) { for (DataLayoutEntryInterface entry : params) if (llvm::dyn_cast_if_present(entry.getKey()) == type) - return 8 * - cast(entry.getValue()).getValue().getZExtValue(); - return 8 * iType.getIntOrFloatBitWidth(); + return llvm::TypeSize::Fixed( + 8 * + cast(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); } };