13ba14fa0SAlex Zinenko //===- DataLayoutInterfacesTest.cpp - Unit Tests for Data Layouts ---------===// 23ba14fa0SAlex Zinenko // 33ba14fa0SAlex Zinenko // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43ba14fa0SAlex Zinenko // See https://llvm.org/LICENSE.txt for license information. 53ba14fa0SAlex Zinenko // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63ba14fa0SAlex Zinenko // 73ba14fa0SAlex Zinenko //===----------------------------------------------------------------------===// 83ba14fa0SAlex Zinenko 93ba14fa0SAlex Zinenko #include "mlir/Interfaces/DataLayoutInterfaces.h" 103ba14fa0SAlex Zinenko #include "mlir/Dialect/DLTI/DLTI.h" 113ba14fa0SAlex Zinenko #include "mlir/IR/Builders.h" 123ba14fa0SAlex Zinenko #include "mlir/IR/BuiltinOps.h" 133ba14fa0SAlex Zinenko #include "mlir/IR/Dialect.h" 143ba14fa0SAlex Zinenko #include "mlir/IR/DialectImplementation.h" 153ba14fa0SAlex Zinenko #include "mlir/IR/OpDefinition.h" 163ba14fa0SAlex Zinenko #include "mlir/IR/OpImplementation.h" 179eaff423SRiver Riddle #include "mlir/Parser/Parser.h" 183ba14fa0SAlex Zinenko 193ba14fa0SAlex Zinenko #include <gtest/gtest.h> 203ba14fa0SAlex Zinenko 213ba14fa0SAlex Zinenko using namespace mlir; 223ba14fa0SAlex Zinenko 233ba14fa0SAlex Zinenko namespace { 243ba14fa0SAlex Zinenko constexpr static llvm::StringLiteral kAttrName = "dltest.layout"; 25a2acf313SChristian Ulmann constexpr static llvm::StringLiteral kEndiannesKeyName = "dltest.endianness"; 26382eb7c2SJan Sjodin constexpr static llvm::StringLiteral kAllocaKeyName = 27382eb7c2SJan Sjodin "dltest.alloca_memory_space"; 28c1ed45a2Sagozillon constexpr static llvm::StringLiteral kProgramKeyName = 29c1ed45a2Sagozillon "dltest.program_memory_space"; 30c1ed45a2Sagozillon constexpr static llvm::StringLiteral kGlobalKeyName = 31c1ed45a2Sagozillon "dltest.global_memory_space"; 329d69bca1STobias Gysi constexpr static llvm::StringLiteral kStackAlignmentKeyName = 339d69bca1STobias Gysi "dltest.stack_alignment"; 343ba14fa0SAlex Zinenko 35abd95342SNiranjan Hasabnis constexpr static llvm::StringLiteral kTargetSystemDescAttrName = 36abd95342SNiranjan Hasabnis "dl_target_sys_desc_test.target_system_spec"; 37abd95342SNiranjan Hasabnis 383ba14fa0SAlex Zinenko /// Trivial array storage for the custom data layout spec attribute, just a list 393ba14fa0SAlex Zinenko /// of entries. 403ba14fa0SAlex Zinenko class DataLayoutSpecStorage : public AttributeStorage { 413ba14fa0SAlex Zinenko public: 423ba14fa0SAlex Zinenko using KeyTy = ArrayRef<DataLayoutEntryInterface>; 433ba14fa0SAlex Zinenko 443ba14fa0SAlex Zinenko DataLayoutSpecStorage(ArrayRef<DataLayoutEntryInterface> entries) 453ba14fa0SAlex Zinenko : entries(entries) {} 463ba14fa0SAlex Zinenko 473ba14fa0SAlex Zinenko bool operator==(const KeyTy &key) const { return key == entries; } 483ba14fa0SAlex Zinenko 493ba14fa0SAlex Zinenko static DataLayoutSpecStorage *construct(AttributeStorageAllocator &allocator, 503ba14fa0SAlex Zinenko const KeyTy &key) { 513ba14fa0SAlex Zinenko return new (allocator.allocate<DataLayoutSpecStorage>()) 523ba14fa0SAlex Zinenko DataLayoutSpecStorage(allocator.copyInto(key)); 533ba14fa0SAlex Zinenko } 543ba14fa0SAlex Zinenko 553ba14fa0SAlex Zinenko ArrayRef<DataLayoutEntryInterface> entries; 563ba14fa0SAlex Zinenko }; 573ba14fa0SAlex Zinenko 583ba14fa0SAlex Zinenko /// Simple data layout spec containing a list of entries that always verifies 593ba14fa0SAlex Zinenko /// as valid. 603ba14fa0SAlex Zinenko struct CustomDataLayoutSpec 6134a88bbcSRolf Morel : public Attribute::AttrBase< 6234a88bbcSRolf Morel CustomDataLayoutSpec, Attribute, DataLayoutSpecStorage, 6334a88bbcSRolf Morel DLTIQueryInterface::Trait, DataLayoutSpecInterface::Trait> { 645e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CustomDataLayoutSpec) 655e50dd04SRiver Riddle 663ba14fa0SAlex Zinenko using Base::Base; 673dbac2c0SFehr Mathieu 683dbac2c0SFehr Mathieu static constexpr StringLiteral name = "test.custom_data_layout_spec"; 693dbac2c0SFehr Mathieu 703ba14fa0SAlex Zinenko static CustomDataLayoutSpec get(MLIRContext *ctx, 713ba14fa0SAlex Zinenko ArrayRef<DataLayoutEntryInterface> entries) { 723ba14fa0SAlex Zinenko return Base::get(ctx, entries); 733ba14fa0SAlex Zinenko } 743ba14fa0SAlex Zinenko CustomDataLayoutSpec 753ba14fa0SAlex Zinenko combineWith(ArrayRef<DataLayoutSpecInterface> specs) const { 763ba14fa0SAlex Zinenko return *this; 773ba14fa0SAlex Zinenko } 783ba14fa0SAlex Zinenko DataLayoutEntryListRef getEntries() const { return getImpl()->entries; } 793ba14fa0SAlex Zinenko LogicalResult verifySpec(Location loc) { return success(); } 80a2acf313SChristian Ulmann StringAttr getEndiannessIdentifier(MLIRContext *context) const { 81a2acf313SChristian Ulmann return Builder(context).getStringAttr(kEndiannesKeyName); 82a2acf313SChristian Ulmann } 83382eb7c2SJan Sjodin StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const { 84382eb7c2SJan Sjodin return Builder(context).getStringAttr(kAllocaKeyName); 85382eb7c2SJan Sjodin } 86c1ed45a2Sagozillon StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const { 87c1ed45a2Sagozillon return Builder(context).getStringAttr(kProgramKeyName); 88c1ed45a2Sagozillon } 89c1ed45a2Sagozillon StringAttr getGlobalMemorySpaceIdentifier(MLIRContext *context) const { 90c1ed45a2Sagozillon return Builder(context).getStringAttr(kGlobalKeyName); 91c1ed45a2Sagozillon } 929d69bca1STobias Gysi StringAttr getStackAlignmentIdentifier(MLIRContext *context) const { 939d69bca1STobias Gysi return Builder(context).getStringAttr(kStackAlignmentKeyName); 949d69bca1STobias Gysi } 9534a88bbcSRolf Morel FailureOr<Attribute> query(DataLayoutEntryKey key) const { 9634a88bbcSRolf Morel return llvm::cast<mlir::DataLayoutSpecInterface>(*this).queryHelper(key); 9734a88bbcSRolf Morel } 983ba14fa0SAlex Zinenko }; 993ba14fa0SAlex Zinenko 100abd95342SNiranjan Hasabnis class TargetSystemSpecStorage : public AttributeStorage { 101abd95342SNiranjan Hasabnis public: 102*5c1752e3SRolf Morel using KeyTy = ArrayRef<DataLayoutEntryInterface>; 103abd95342SNiranjan Hasabnis 104*5c1752e3SRolf Morel TargetSystemSpecStorage(ArrayRef<DataLayoutEntryInterface> entries) 105abd95342SNiranjan Hasabnis : entries(entries) {} 106abd95342SNiranjan Hasabnis 107abd95342SNiranjan Hasabnis bool operator==(const KeyTy &key) const { return key == entries; } 108abd95342SNiranjan Hasabnis 109abd95342SNiranjan Hasabnis static TargetSystemSpecStorage * 110abd95342SNiranjan Hasabnis construct(AttributeStorageAllocator &allocator, const KeyTy &key) { 111abd95342SNiranjan Hasabnis return new (allocator.allocate<TargetSystemSpecStorage>()) 112abd95342SNiranjan Hasabnis TargetSystemSpecStorage(allocator.copyInto(key)); 113abd95342SNiranjan Hasabnis } 114abd95342SNiranjan Hasabnis 115*5c1752e3SRolf Morel ArrayRef<DataLayoutEntryInterface> entries; 116abd95342SNiranjan Hasabnis }; 117abd95342SNiranjan Hasabnis 118abd95342SNiranjan Hasabnis struct CustomTargetSystemSpec 11934a88bbcSRolf Morel : public Attribute::AttrBase< 12034a88bbcSRolf Morel CustomTargetSystemSpec, Attribute, TargetSystemSpecStorage, 12134a88bbcSRolf Morel DLTIQueryInterface::Trait, TargetSystemSpecInterface::Trait> { 122abd95342SNiranjan Hasabnis MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CustomDataLayoutSpec) 123abd95342SNiranjan Hasabnis 124abd95342SNiranjan Hasabnis using Base::Base; 125abd95342SNiranjan Hasabnis 126abd95342SNiranjan Hasabnis static constexpr StringLiteral name = "test.custom_target_system_spec"; 127abd95342SNiranjan Hasabnis 128abd95342SNiranjan Hasabnis static CustomTargetSystemSpec 129*5c1752e3SRolf Morel get(MLIRContext *ctx, ArrayRef<DataLayoutEntryInterface> entries) { 130abd95342SNiranjan Hasabnis return Base::get(ctx, entries); 131abd95342SNiranjan Hasabnis } 132*5c1752e3SRolf Morel ArrayRef<DataLayoutEntryInterface> getEntries() const { 133abd95342SNiranjan Hasabnis return getImpl()->entries; 134abd95342SNiranjan Hasabnis } 135abd95342SNiranjan Hasabnis LogicalResult verifySpec(Location loc) { return success(); } 136abd95342SNiranjan Hasabnis std::optional<TargetDeviceSpecInterface> 137abd95342SNiranjan Hasabnis getDeviceSpecForDeviceID(TargetSystemSpecInterface::DeviceID deviceID) { 138abd95342SNiranjan Hasabnis for (const auto &entry : getEntries()) { 139*5c1752e3SRolf Morel if (entry.getKey() == DataLayoutEntryKey(deviceID)) 140*5c1752e3SRolf Morel if (auto deviceSpec = 141*5c1752e3SRolf Morel llvm::dyn_cast<TargetDeviceSpecInterface>(entry.getValue())) 142*5c1752e3SRolf Morel return deviceSpec; 143abd95342SNiranjan Hasabnis } 144abd95342SNiranjan Hasabnis return std::nullopt; 145abd95342SNiranjan Hasabnis } 14634a88bbcSRolf Morel FailureOr<Attribute> query(DataLayoutEntryKey key) const { 14734a88bbcSRolf Morel return llvm::cast<mlir::TargetSystemSpecInterface>(*this).queryHelper(key); 14834a88bbcSRolf Morel } 149abd95342SNiranjan Hasabnis }; 150abd95342SNiranjan Hasabnis 1513ba14fa0SAlex Zinenko /// A type subject to data layout that exits the program if it is queried more 1523ba14fa0SAlex Zinenko /// than once. Handy to check if the cache works. 1533ba14fa0SAlex Zinenko struct SingleQueryType 1543ba14fa0SAlex Zinenko : public Type::TypeBase<SingleQueryType, Type, TypeStorage, 1553ba14fa0SAlex Zinenko DataLayoutTypeInterface::Trait> { 1565e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(SingleQueryType) 1575e50dd04SRiver Riddle 1583ba14fa0SAlex Zinenko using Base::Base; 1593ba14fa0SAlex Zinenko 1603dbac2c0SFehr Mathieu static constexpr StringLiteral name = "test.single_query"; 1613dbac2c0SFehr Mathieu 1623ba14fa0SAlex Zinenko static SingleQueryType get(MLIRContext *ctx) { return Base::get(ctx); } 1633ba14fa0SAlex Zinenko 1648134a8fcSOleksandr "Alex" Zinenko llvm::TypeSize getTypeSizeInBits(const DataLayout &layout, 165f9cdc61dSAlex Zinenko DataLayoutEntryListRef params) const { 1663ba14fa0SAlex Zinenko static bool executed = false; 1673ba14fa0SAlex Zinenko if (executed) 1683ba14fa0SAlex Zinenko llvm::report_fatal_error("repeated call"); 1693ba14fa0SAlex Zinenko 1703ba14fa0SAlex Zinenko executed = true; 17121646789SSander de Smalen return llvm::TypeSize::getFixed(1); 1723ba14fa0SAlex Zinenko } 1733ba14fa0SAlex Zinenko 1748134a8fcSOleksandr "Alex" Zinenko uint64_t getABIAlignment(const DataLayout &layout, 1753ba14fa0SAlex Zinenko DataLayoutEntryListRef params) { 1763ba14fa0SAlex Zinenko static bool executed = false; 1773ba14fa0SAlex Zinenko if (executed) 1783ba14fa0SAlex Zinenko llvm::report_fatal_error("repeated call"); 1793ba14fa0SAlex Zinenko 1803ba14fa0SAlex Zinenko executed = true; 1813ba14fa0SAlex Zinenko return 2; 1823ba14fa0SAlex Zinenko } 1833ba14fa0SAlex Zinenko 1848134a8fcSOleksandr "Alex" Zinenko uint64_t getPreferredAlignment(const DataLayout &layout, 1853ba14fa0SAlex Zinenko DataLayoutEntryListRef params) { 1863ba14fa0SAlex Zinenko static bool executed = false; 1873ba14fa0SAlex Zinenko if (executed) 1883ba14fa0SAlex Zinenko llvm::report_fatal_error("repeated call"); 1893ba14fa0SAlex Zinenko 1903ba14fa0SAlex Zinenko executed = true; 1913ba14fa0SAlex Zinenko return 4; 1923ba14fa0SAlex Zinenko } 193382eb7c2SJan Sjodin 194a2acf313SChristian Ulmann Attribute getEndianness(DataLayoutEntryInterface entry) { 195a2acf313SChristian Ulmann static bool executed = false; 196a2acf313SChristian Ulmann if (executed) 197a2acf313SChristian Ulmann llvm::report_fatal_error("repeated call"); 198a2acf313SChristian Ulmann 199a2acf313SChristian Ulmann executed = true; 200a2acf313SChristian Ulmann return Attribute(); 201a2acf313SChristian Ulmann } 202a2acf313SChristian Ulmann 203382eb7c2SJan Sjodin Attribute getAllocaMemorySpace(DataLayoutEntryInterface entry) { 204382eb7c2SJan Sjodin static bool executed = false; 205382eb7c2SJan Sjodin if (executed) 206382eb7c2SJan Sjodin llvm::report_fatal_error("repeated call"); 207382eb7c2SJan Sjodin 208382eb7c2SJan Sjodin executed = true; 209382eb7c2SJan Sjodin return Attribute(); 210382eb7c2SJan Sjodin } 211c1ed45a2Sagozillon 212c1ed45a2Sagozillon Attribute getProgramMemorySpace(DataLayoutEntryInterface entry) { 213c1ed45a2Sagozillon static bool executed = false; 214c1ed45a2Sagozillon if (executed) 215c1ed45a2Sagozillon llvm::report_fatal_error("repeated call"); 216c1ed45a2Sagozillon 217c1ed45a2Sagozillon executed = true; 218c1ed45a2Sagozillon return Attribute(); 219c1ed45a2Sagozillon } 220c1ed45a2Sagozillon 221c1ed45a2Sagozillon Attribute getGlobalMemorySpace(DataLayoutEntryInterface entry) { 222c1ed45a2Sagozillon static bool executed = false; 223c1ed45a2Sagozillon if (executed) 224c1ed45a2Sagozillon llvm::report_fatal_error("repeated call"); 225c1ed45a2Sagozillon 226c1ed45a2Sagozillon executed = true; 227c1ed45a2Sagozillon return Attribute(); 228c1ed45a2Sagozillon } 2293ba14fa0SAlex Zinenko }; 2303ba14fa0SAlex Zinenko 2313ba14fa0SAlex Zinenko /// A types that is not subject to data layout. 2323ba14fa0SAlex Zinenko struct TypeNoLayout : public Type::TypeBase<TypeNoLayout, Type, TypeStorage> { 2335e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TypeNoLayout) 2345e50dd04SRiver Riddle 2353ba14fa0SAlex Zinenko using Base::Base; 2363ba14fa0SAlex Zinenko 2373dbac2c0SFehr Mathieu static constexpr StringLiteral name = "test.no_layout"; 2383dbac2c0SFehr Mathieu 2393ba14fa0SAlex Zinenko static TypeNoLayout get(MLIRContext *ctx) { return Base::get(ctx); } 2403ba14fa0SAlex Zinenko }; 2413ba14fa0SAlex Zinenko 2423ba14fa0SAlex Zinenko /// An op that serves as scope for data layout queries with the relevant 2433ba14fa0SAlex Zinenko /// attribute attached. This can handle data layout requests for the built-in 2443ba14fa0SAlex Zinenko /// types itself. 2453ba14fa0SAlex Zinenko struct OpWithLayout : public Op<OpWithLayout, DataLayoutOpInterface::Trait> { 2465e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(OpWithLayout) 2475e50dd04SRiver Riddle 2483ba14fa0SAlex Zinenko using Op::Op; 249e4e31e19SRiver Riddle static ArrayRef<StringRef> getAttributeNames() { return {}; } 2503ba14fa0SAlex Zinenko 2513ba14fa0SAlex Zinenko static StringRef getOperationName() { return "dltest.op_with_layout"; } 2523ba14fa0SAlex Zinenko 2533ba14fa0SAlex Zinenko DataLayoutSpecInterface getDataLayoutSpec() { 2543ba14fa0SAlex Zinenko return getOperation()->getAttrOfType<DataLayoutSpecInterface>(kAttrName); 2553ba14fa0SAlex Zinenko } 2563ba14fa0SAlex Zinenko 257abd95342SNiranjan Hasabnis TargetSystemSpecInterface getTargetSystemSpec() { 258abd95342SNiranjan Hasabnis return getOperation()->getAttrOfType<TargetSystemSpecInterface>( 259abd95342SNiranjan Hasabnis kTargetSystemDescAttrName); 260abd95342SNiranjan Hasabnis } 261abd95342SNiranjan Hasabnis 2628134a8fcSOleksandr "Alex" Zinenko static llvm::TypeSize getTypeSizeInBits(Type type, 2638134a8fcSOleksandr "Alex" Zinenko const DataLayout &dataLayout, 2643ba14fa0SAlex Zinenko DataLayoutEntryListRef params) { 2653ba14fa0SAlex Zinenko // Make a recursive query. 2665550c821STres Popp if (isa<FloatType>(type)) 267f9cdc61dSAlex Zinenko return dataLayout.getTypeSizeInBits( 2683ba14fa0SAlex Zinenko IntegerType::get(type.getContext(), type.getIntOrFloatBitWidth())); 2693ba14fa0SAlex Zinenko 2703ba14fa0SAlex Zinenko // Handle built-in types that are not handled by the default process. 2715550c821STres Popp if (auto iType = dyn_cast<IntegerType>(type)) { 2723ba14fa0SAlex Zinenko for (DataLayoutEntryInterface entry : params) 27368f58812STres Popp if (llvm::dyn_cast_if_present<Type>(entry.getKey()) == type) 27421646789SSander de Smalen return llvm::TypeSize::getFixed( 2758134a8fcSOleksandr "Alex" Zinenko 8 * 2768134a8fcSOleksandr "Alex" Zinenko cast<IntegerAttr>(entry.getValue()).getValue().getZExtValue()); 27721646789SSander de Smalen return llvm::TypeSize::getFixed(8 * iType.getIntOrFloatBitWidth()); 2783ba14fa0SAlex Zinenko } 2793ba14fa0SAlex Zinenko 2803ba14fa0SAlex Zinenko // Use the default process for everything else. 2813ba14fa0SAlex Zinenko return detail::getDefaultTypeSize(type, dataLayout, params); 2823ba14fa0SAlex Zinenko } 2833ba14fa0SAlex Zinenko 2848134a8fcSOleksandr "Alex" Zinenko static uint64_t getTypeABIAlignment(Type type, const DataLayout &dataLayout, 2853ba14fa0SAlex Zinenko DataLayoutEntryListRef params) { 2863ba14fa0SAlex Zinenko return llvm::PowerOf2Ceil(getTypeSize(type, dataLayout, params)); 2873ba14fa0SAlex Zinenko } 2883ba14fa0SAlex Zinenko 2898134a8fcSOleksandr "Alex" Zinenko static uint64_t getTypePreferredAlignment(Type type, 2903ba14fa0SAlex Zinenko const DataLayout &dataLayout, 2913ba14fa0SAlex Zinenko DataLayoutEntryListRef params) { 2923ba14fa0SAlex Zinenko return 2 * getTypeABIAlignment(type, dataLayout, params); 2933ba14fa0SAlex Zinenko } 2943ba14fa0SAlex Zinenko }; 2953ba14fa0SAlex Zinenko 296f9cdc61dSAlex Zinenko struct OpWith7BitByte 297f9cdc61dSAlex Zinenko : public Op<OpWith7BitByte, DataLayoutOpInterface::Trait> { 2985e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(OpWith7BitByte) 2995e50dd04SRiver Riddle 300f9cdc61dSAlex Zinenko using Op::Op; 301e4e31e19SRiver Riddle static ArrayRef<StringRef> getAttributeNames() { return {}; } 302f9cdc61dSAlex Zinenko 303f9cdc61dSAlex Zinenko static StringRef getOperationName() { return "dltest.op_with_7bit_byte"; } 304f9cdc61dSAlex Zinenko 305f9cdc61dSAlex Zinenko DataLayoutSpecInterface getDataLayoutSpec() { 306f9cdc61dSAlex Zinenko return getOperation()->getAttrOfType<DataLayoutSpecInterface>(kAttrName); 307f9cdc61dSAlex Zinenko } 308f9cdc61dSAlex Zinenko 309abd95342SNiranjan Hasabnis TargetSystemSpecInterface getTargetSystemSpec() { 310abd95342SNiranjan Hasabnis return getOperation()->getAttrOfType<TargetSystemSpecInterface>( 311abd95342SNiranjan Hasabnis kTargetSystemDescAttrName); 312abd95342SNiranjan Hasabnis } 313abd95342SNiranjan Hasabnis 314f9cdc61dSAlex Zinenko // Bytes are assumed to be 7-bit here. 3158134a8fcSOleksandr "Alex" Zinenko static llvm::TypeSize getTypeSize(Type type, const DataLayout &dataLayout, 316f9cdc61dSAlex Zinenko DataLayoutEntryListRef params) { 3178134a8fcSOleksandr "Alex" Zinenko return mlir::detail::divideCeil(dataLayout.getTypeSizeInBits(type), 7); 318f9cdc61dSAlex Zinenko } 319f9cdc61dSAlex Zinenko }; 320f9cdc61dSAlex Zinenko 3213ba14fa0SAlex Zinenko /// A dialect putting all the above together. 3223ba14fa0SAlex Zinenko struct DLTestDialect : Dialect { 3235e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(DLTestDialect) 3245e50dd04SRiver Riddle 3253ba14fa0SAlex Zinenko explicit DLTestDialect(MLIRContext *ctx) 3263ba14fa0SAlex Zinenko : Dialect(getDialectNamespace(), ctx, TypeID::get<DLTestDialect>()) { 3273ba14fa0SAlex Zinenko ctx->getOrLoadDialect<DLTIDialect>(); 3283ba14fa0SAlex Zinenko addAttributes<CustomDataLayoutSpec>(); 329f9cdc61dSAlex Zinenko addOperations<OpWithLayout, OpWith7BitByte>(); 3303ba14fa0SAlex Zinenko addTypes<SingleQueryType, TypeNoLayout>(); 3313ba14fa0SAlex Zinenko } 3323ba14fa0SAlex Zinenko static StringRef getDialectNamespace() { return "dltest"; } 3333ba14fa0SAlex Zinenko 3343ba14fa0SAlex Zinenko void printAttribute(Attribute attr, 3353ba14fa0SAlex Zinenko DialectAsmPrinter &printer) const override { 3363ba14fa0SAlex Zinenko printer << "spec<"; 3375550c821STres Popp llvm::interleaveComma(cast<CustomDataLayoutSpec>(attr).getEntries(), 3383ba14fa0SAlex Zinenko printer); 3393ba14fa0SAlex Zinenko printer << ">"; 3403ba14fa0SAlex Zinenko } 3413ba14fa0SAlex Zinenko 3423ba14fa0SAlex Zinenko Attribute parseAttribute(DialectAsmParser &parser, Type type) const override { 3433ba14fa0SAlex Zinenko bool ok = 3443ba14fa0SAlex Zinenko succeeded(parser.parseKeyword("spec")) && succeeded(parser.parseLess()); 3453ba14fa0SAlex Zinenko (void)ok; 3463ba14fa0SAlex Zinenko assert(ok); 3473ba14fa0SAlex Zinenko if (succeeded(parser.parseOptionalGreater())) 348fb093c83SChris Lattner return CustomDataLayoutSpec::get(parser.getContext(), {}); 3493ba14fa0SAlex Zinenko 3503ba14fa0SAlex Zinenko SmallVector<DataLayoutEntryInterface> entries; 3511d7b5cd5SChris Lattner ok = succeeded(parser.parseCommaSeparatedList([&]() { 3523ba14fa0SAlex Zinenko entries.emplace_back(); 3533ba14fa0SAlex Zinenko ok = succeeded(parser.parseAttribute(entries.back())); 3543ba14fa0SAlex Zinenko assert(ok); 355167bbfcbSJakub Tucholski return success(); 3561d7b5cd5SChris Lattner })); 3571d7b5cd5SChris Lattner assert(ok); 3583ba14fa0SAlex Zinenko ok = succeeded(parser.parseGreater()); 3593ba14fa0SAlex Zinenko assert(ok); 360fb093c83SChris Lattner return CustomDataLayoutSpec::get(parser.getContext(), entries); 3613ba14fa0SAlex Zinenko } 3623ba14fa0SAlex Zinenko 3633ba14fa0SAlex Zinenko void printType(Type type, DialectAsmPrinter &printer) const override { 3645550c821STres Popp if (isa<SingleQueryType>(type)) 3653ba14fa0SAlex Zinenko printer << "single_query"; 3663ba14fa0SAlex Zinenko else 3673ba14fa0SAlex Zinenko printer << "no_layout"; 3683ba14fa0SAlex Zinenko } 3693ba14fa0SAlex Zinenko 3703ba14fa0SAlex Zinenko Type parseType(DialectAsmParser &parser) const override { 3713ba14fa0SAlex Zinenko bool ok = succeeded(parser.parseKeyword("single_query")); 3723ba14fa0SAlex Zinenko (void)ok; 3733ba14fa0SAlex Zinenko assert(ok); 374fb093c83SChris Lattner return SingleQueryType::get(parser.getContext()); 3753ba14fa0SAlex Zinenko } 3763ba14fa0SAlex Zinenko }; 3773ba14fa0SAlex Zinenko 378abd95342SNiranjan Hasabnis /// A dialect to test DLTI's target system spec and related attributes 379abd95342SNiranjan Hasabnis struct DLTargetSystemDescTestDialect : public Dialect { 380abd95342SNiranjan Hasabnis MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(DLTargetSystemDescTestDialect) 381abd95342SNiranjan Hasabnis 382abd95342SNiranjan Hasabnis explicit DLTargetSystemDescTestDialect(MLIRContext *ctx) 383abd95342SNiranjan Hasabnis : Dialect(getDialectNamespace(), ctx, 384abd95342SNiranjan Hasabnis TypeID::get<DLTargetSystemDescTestDialect>()) { 385abd95342SNiranjan Hasabnis ctx->getOrLoadDialect<DLTIDialect>(); 386abd95342SNiranjan Hasabnis addAttributes<CustomTargetSystemSpec>(); 387abd95342SNiranjan Hasabnis } 388abd95342SNiranjan Hasabnis static StringRef getDialectNamespace() { return "dl_target_sys_desc_test"; } 389abd95342SNiranjan Hasabnis 390abd95342SNiranjan Hasabnis void printAttribute(Attribute attr, 391abd95342SNiranjan Hasabnis DialectAsmPrinter &printer) const override { 392abd95342SNiranjan Hasabnis printer << "target_system_spec<"; 393*5c1752e3SRolf Morel llvm::interleaveComma(cast<CustomTargetSystemSpec>(attr).getEntries(), 394*5c1752e3SRolf Morel printer, [&](const auto &it) { 395*5c1752e3SRolf Morel printer << dyn_cast<StringAttr>(it.getKey()) << ":" 396*5c1752e3SRolf Morel << it.getValue(); 397*5c1752e3SRolf Morel }); 398abd95342SNiranjan Hasabnis printer << ">"; 399abd95342SNiranjan Hasabnis } 400abd95342SNiranjan Hasabnis 401abd95342SNiranjan Hasabnis Attribute parseAttribute(DialectAsmParser &parser, Type type) const override { 402abd95342SNiranjan Hasabnis bool ok = succeeded(parser.parseKeyword("target_system_spec")) && 403abd95342SNiranjan Hasabnis succeeded(parser.parseLess()); 404abd95342SNiranjan Hasabnis (void)ok; 405abd95342SNiranjan Hasabnis assert(ok); 406abd95342SNiranjan Hasabnis if (succeeded(parser.parseOptionalGreater())) 407abd95342SNiranjan Hasabnis return CustomTargetSystemSpec::get(parser.getContext(), {}); 408abd95342SNiranjan Hasabnis 409*5c1752e3SRolf Morel auto parseTargetDeviceSpecEntry = 410*5c1752e3SRolf Morel [&](AsmParser &parser) -> FailureOr<TargetDeviceSpecEntry> { 411abd95342SNiranjan Hasabnis std::string deviceID; 412abd95342SNiranjan Hasabnis if (failed(parser.parseString(&deviceID))) { 413abd95342SNiranjan Hasabnis parser.emitError(parser.getCurrentLocation()) 414abd95342SNiranjan Hasabnis << "DeviceID is missing, or is not of string type"; 415abd95342SNiranjan Hasabnis return failure(); 416abd95342SNiranjan Hasabnis } 417abd95342SNiranjan Hasabnis if (failed(parser.parseColon())) { 418abd95342SNiranjan Hasabnis parser.emitError(parser.getCurrentLocation()) << "Missing colon"; 419abd95342SNiranjan Hasabnis return failure(); 420abd95342SNiranjan Hasabnis } 421abd95342SNiranjan Hasabnis 422abd95342SNiranjan Hasabnis TargetDeviceSpecInterface targetDeviceSpec; 423abd95342SNiranjan Hasabnis if (failed(parser.parseAttribute(targetDeviceSpec))) { 424abd95342SNiranjan Hasabnis parser.emitError(parser.getCurrentLocation()) 425abd95342SNiranjan Hasabnis << "Error in parsing target device spec"; 426abd95342SNiranjan Hasabnis return failure(); 427abd95342SNiranjan Hasabnis } 428abd95342SNiranjan Hasabnis return std::make_pair(parser.getBuilder().getStringAttr(deviceID), 429abd95342SNiranjan Hasabnis targetDeviceSpec); 430abd95342SNiranjan Hasabnis }; 431abd95342SNiranjan Hasabnis 432*5c1752e3SRolf Morel SmallVector<DataLayoutEntryInterface> entries; 433abd95342SNiranjan Hasabnis ok = succeeded(parser.parseCommaSeparatedList([&]() { 434*5c1752e3SRolf Morel auto deviceIDAndTargetDeviceSpecPair = parseTargetDeviceSpecEntry(parser); 435abd95342SNiranjan Hasabnis ok = succeeded(deviceIDAndTargetDeviceSpecPair); 436abd95342SNiranjan Hasabnis assert(ok); 437*5c1752e3SRolf Morel auto entry = 438*5c1752e3SRolf Morel DataLayoutEntryAttr::get(deviceIDAndTargetDeviceSpecPair->first, 439*5c1752e3SRolf Morel deviceIDAndTargetDeviceSpecPair->second); 440*5c1752e3SRolf Morel entries.push_back(entry); 441abd95342SNiranjan Hasabnis return success(); 442abd95342SNiranjan Hasabnis })); 443abd95342SNiranjan Hasabnis assert(ok); 444abd95342SNiranjan Hasabnis ok = succeeded(parser.parseGreater()); 445abd95342SNiranjan Hasabnis assert(ok); 446abd95342SNiranjan Hasabnis return CustomTargetSystemSpec::get(parser.getContext(), entries); 447abd95342SNiranjan Hasabnis } 448abd95342SNiranjan Hasabnis }; 449abd95342SNiranjan Hasabnis 450be0a7e9fSMehdi Amini } // namespace 4513ba14fa0SAlex Zinenko 4523ba14fa0SAlex Zinenko TEST(DataLayout, FallbackDefault) { 4533ba14fa0SAlex Zinenko const char *ir = R"MLIR( 454842d2435SAlex Zinenko module {} 455842d2435SAlex Zinenko )MLIR"; 456842d2435SAlex Zinenko 457842d2435SAlex Zinenko DialectRegistry registry; 458842d2435SAlex Zinenko registry.insert<DLTIDialect, DLTestDialect>(); 459842d2435SAlex Zinenko MLIRContext ctx(registry); 460842d2435SAlex Zinenko 461dfaadf6bSChristian Sigg OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx); 462842d2435SAlex Zinenko DataLayout layout(module.get()); 463842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeSize(IntegerType::get(&ctx, 42)), 6u); 464842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeSize(Float16Type::get(&ctx)), 2u); 465842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(IntegerType::get(&ctx, 42)), 42u); 466842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(Float16Type::get(&ctx)), 16u); 467842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeABIAlignment(IntegerType::get(&ctx, 42)), 8u); 468842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeABIAlignment(Float16Type::get(&ctx)), 2u); 469842d2435SAlex Zinenko EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 42)), 8u); 470842d2435SAlex Zinenko EXPECT_EQ(layout.getTypePreferredAlignment(Float16Type::get(&ctx)), 2u); 471382eb7c2SJan Sjodin 472a2acf313SChristian Ulmann EXPECT_EQ(layout.getEndianness(), Attribute()); 473382eb7c2SJan Sjodin EXPECT_EQ(layout.getAllocaMemorySpace(), Attribute()); 474c1ed45a2Sagozillon EXPECT_EQ(layout.getProgramMemorySpace(), Attribute()); 475c1ed45a2Sagozillon EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute()); 4769d69bca1STobias Gysi EXPECT_EQ(layout.getStackAlignment(), 0u); 477842d2435SAlex Zinenko } 478842d2435SAlex Zinenko 479842d2435SAlex Zinenko TEST(DataLayout, NullSpec) { 480842d2435SAlex Zinenko const char *ir = R"MLIR( 4813ba14fa0SAlex Zinenko "dltest.op_with_layout"() : () -> () 4823ba14fa0SAlex Zinenko )MLIR"; 4833ba14fa0SAlex Zinenko 4843ba14fa0SAlex Zinenko DialectRegistry registry; 4853ba14fa0SAlex Zinenko registry.insert<DLTIDialect, DLTestDialect>(); 4863ba14fa0SAlex Zinenko MLIRContext ctx(registry); 4873ba14fa0SAlex Zinenko 488dfaadf6bSChristian Sigg OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx); 4893ba14fa0SAlex Zinenko auto op = 4903ba14fa0SAlex Zinenko cast<DataLayoutOpInterface>(module->getBody()->getOperations().front()); 4913ba14fa0SAlex Zinenko DataLayout layout(op); 492382eb7c2SJan Sjodin 493842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeSize(IntegerType::get(&ctx, 42)), 42u); 494842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeSize(Float16Type::get(&ctx)), 16u); 495842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(IntegerType::get(&ctx, 42)), 8u * 42u); 496842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(Float16Type::get(&ctx)), 8u * 16u); 497842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeABIAlignment(IntegerType::get(&ctx, 42)), 64u); 498842d2435SAlex Zinenko EXPECT_EQ(layout.getTypeABIAlignment(Float16Type::get(&ctx)), 16u); 499842d2435SAlex Zinenko EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 42)), 128u); 500842d2435SAlex Zinenko EXPECT_EQ(layout.getTypePreferredAlignment(Float16Type::get(&ctx)), 32u); 501adda5973STobias Gysi EXPECT_EQ(layout.getTypeIndexBitwidth(Float16Type::get(&ctx)), std::nullopt); 502adda5973STobias Gysi EXPECT_EQ(layout.getTypeIndexBitwidth(IndexType::get(&ctx)), 64u); 503382eb7c2SJan Sjodin 504a2acf313SChristian Ulmann EXPECT_EQ(layout.getEndianness(), Attribute()); 505382eb7c2SJan Sjodin EXPECT_EQ(layout.getAllocaMemorySpace(), Attribute()); 506c1ed45a2Sagozillon EXPECT_EQ(layout.getProgramMemorySpace(), Attribute()); 507c1ed45a2Sagozillon EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute()); 5089d69bca1STobias Gysi EXPECT_EQ(layout.getStackAlignment(), 0u); 509abd95342SNiranjan Hasabnis 510bdeee9b1SNiranjan Hasabnis EXPECT_EQ(layout.getDevicePropertyValue( 511abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("CPU" /* device ID*/), 512abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("L1_cache_size_in_bytes")), 513abd95342SNiranjan Hasabnis std::nullopt); 514bdeee9b1SNiranjan Hasabnis EXPECT_EQ(layout.getDevicePropertyValue( 515abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("CPU" /* device ID*/), 516abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("max_vector_width")), 517abd95342SNiranjan Hasabnis std::nullopt); 5183ba14fa0SAlex Zinenko } 5193ba14fa0SAlex Zinenko 5203ba14fa0SAlex Zinenko TEST(DataLayout, EmptySpec) { 5213ba14fa0SAlex Zinenko const char *ir = R"MLIR( 5223ba14fa0SAlex Zinenko "dltest.op_with_layout"() { dltest.layout = #dltest.spec< > } : () -> () 5233ba14fa0SAlex Zinenko )MLIR"; 5243ba14fa0SAlex Zinenko 5253ba14fa0SAlex Zinenko DialectRegistry registry; 5263ba14fa0SAlex Zinenko registry.insert<DLTIDialect, DLTestDialect>(); 5273ba14fa0SAlex Zinenko MLIRContext ctx(registry); 5283ba14fa0SAlex Zinenko 529dfaadf6bSChristian Sigg OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx); 5303ba14fa0SAlex Zinenko auto op = 5313ba14fa0SAlex Zinenko cast<DataLayoutOpInterface>(module->getBody()->getOperations().front()); 5323ba14fa0SAlex Zinenko DataLayout layout(op); 5333ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeSize(IntegerType::get(&ctx, 42)), 42u); 5343ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeSize(Float16Type::get(&ctx)), 16u); 535f9cdc61dSAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(IntegerType::get(&ctx, 42)), 8u * 42u); 536f9cdc61dSAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(Float16Type::get(&ctx)), 8u * 16u); 5373ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeABIAlignment(IntegerType::get(&ctx, 42)), 64u); 5383ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeABIAlignment(Float16Type::get(&ctx)), 16u); 5393ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 42)), 128u); 5403ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypePreferredAlignment(Float16Type::get(&ctx)), 32u); 541adda5973STobias Gysi EXPECT_EQ(layout.getTypeIndexBitwidth(Float16Type::get(&ctx)), std::nullopt); 542adda5973STobias Gysi EXPECT_EQ(layout.getTypeIndexBitwidth(IndexType::get(&ctx)), 64u); 543382eb7c2SJan Sjodin 544a2acf313SChristian Ulmann EXPECT_EQ(layout.getEndianness(), Attribute()); 545382eb7c2SJan Sjodin EXPECT_EQ(layout.getAllocaMemorySpace(), Attribute()); 546c1ed45a2Sagozillon EXPECT_EQ(layout.getProgramMemorySpace(), Attribute()); 547c1ed45a2Sagozillon EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute()); 5489d69bca1STobias Gysi EXPECT_EQ(layout.getStackAlignment(), 0u); 549abd95342SNiranjan Hasabnis 550bdeee9b1SNiranjan Hasabnis EXPECT_EQ(layout.getDevicePropertyValue( 551abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("CPU" /* device ID*/), 552abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("L1_cache_size_in_bytes")), 553abd95342SNiranjan Hasabnis std::nullopt); 554bdeee9b1SNiranjan Hasabnis EXPECT_EQ(layout.getDevicePropertyValue( 555abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("CPU" /* device ID*/), 556abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("max_vector_width")), 557abd95342SNiranjan Hasabnis std::nullopt); 5583ba14fa0SAlex Zinenko } 5593ba14fa0SAlex Zinenko 5603ba14fa0SAlex Zinenko TEST(DataLayout, SpecWithEntries) { 5613ba14fa0SAlex Zinenko const char *ir = R"MLIR( 5623ba14fa0SAlex Zinenko "dltest.op_with_layout"() { dltest.layout = #dltest.spec< 5633ba14fa0SAlex Zinenko #dlti.dl_entry<i42, 5>, 564382eb7c2SJan Sjodin #dlti.dl_entry<i16, 6>, 565adda5973STobias Gysi #dlti.dl_entry<index, 42>, 566a2acf313SChristian Ulmann #dlti.dl_entry<"dltest.endianness", "little">, 5679d69bca1STobias Gysi #dlti.dl_entry<"dltest.alloca_memory_space", 5 : i32>, 568c1ed45a2Sagozillon #dlti.dl_entry<"dltest.program_memory_space", 3 : i32>, 569c1ed45a2Sagozillon #dlti.dl_entry<"dltest.global_memory_space", 2 : i32>, 5709d69bca1STobias Gysi #dlti.dl_entry<"dltest.stack_alignment", 128 : i32> 5713ba14fa0SAlex Zinenko > } : () -> () 5723ba14fa0SAlex Zinenko )MLIR"; 5733ba14fa0SAlex Zinenko 5743ba14fa0SAlex Zinenko DialectRegistry registry; 5753ba14fa0SAlex Zinenko registry.insert<DLTIDialect, DLTestDialect>(); 5763ba14fa0SAlex Zinenko MLIRContext ctx(registry); 5773ba14fa0SAlex Zinenko 578dfaadf6bSChristian Sigg OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx); 5793ba14fa0SAlex Zinenko auto op = 5803ba14fa0SAlex Zinenko cast<DataLayoutOpInterface>(module->getBody()->getOperations().front()); 5813ba14fa0SAlex Zinenko DataLayout layout(op); 5823ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeSize(IntegerType::get(&ctx, 42)), 5u); 5833ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeSize(Float16Type::get(&ctx)), 6u); 584f9cdc61dSAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(IntegerType::get(&ctx, 42)), 40u); 585f9cdc61dSAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(Float16Type::get(&ctx)), 48u); 5863ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeABIAlignment(IntegerType::get(&ctx, 42)), 8u); 5873ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeABIAlignment(Float16Type::get(&ctx)), 8u); 5883ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 42)), 16u); 5893ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypePreferredAlignment(Float16Type::get(&ctx)), 16u); 590adda5973STobias Gysi EXPECT_EQ(layout.getTypeIndexBitwidth(Float16Type::get(&ctx)), std::nullopt); 591adda5973STobias Gysi EXPECT_EQ(layout.getTypeIndexBitwidth(IndexType::get(&ctx)), 42u); 5923ba14fa0SAlex Zinenko 5933ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeSize(IntegerType::get(&ctx, 32)), 32u); 5943ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeSize(Float32Type::get(&ctx)), 32u); 595f9cdc61dSAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(IntegerType::get(&ctx, 32)), 256u); 596f9cdc61dSAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(Float32Type::get(&ctx)), 256u); 5973ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeABIAlignment(IntegerType::get(&ctx, 32)), 32u); 5983ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeABIAlignment(Float32Type::get(&ctx)), 32u); 5993ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 32)), 64u); 6003ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypePreferredAlignment(Float32Type::get(&ctx)), 64u); 601382eb7c2SJan Sjodin 602a2acf313SChristian Ulmann EXPECT_EQ(layout.getEndianness(), Builder(&ctx).getStringAttr("little")); 603382eb7c2SJan Sjodin EXPECT_EQ(layout.getAllocaMemorySpace(), Builder(&ctx).getI32IntegerAttr(5)); 604c1ed45a2Sagozillon EXPECT_EQ(layout.getProgramMemorySpace(), Builder(&ctx).getI32IntegerAttr(3)); 605c1ed45a2Sagozillon EXPECT_EQ(layout.getGlobalMemorySpace(), Builder(&ctx).getI32IntegerAttr(2)); 6069d69bca1STobias Gysi EXPECT_EQ(layout.getStackAlignment(), 128u); 6073ba14fa0SAlex Zinenko } 6083ba14fa0SAlex Zinenko 609abd95342SNiranjan Hasabnis TEST(DataLayout, SpecWithTargetSystemDescEntries) { 610abd95342SNiranjan Hasabnis const char *ir = R"MLIR( 611abd95342SNiranjan Hasabnis module attributes { dl_target_sys_desc_test.target_system_spec = 612abd95342SNiranjan Hasabnis #dl_target_sys_desc_test.target_system_spec< 613abd95342SNiranjan Hasabnis "CPU": #dlti.target_device_spec< 614bdeee9b1SNiranjan Hasabnis #dlti.dl_entry<"L1_cache_size_in_bytes", "4096">, 615bdeee9b1SNiranjan Hasabnis #dlti.dl_entry<"max_vector_op_width", "128">> 616abd95342SNiranjan Hasabnis > } {} 617abd95342SNiranjan Hasabnis )MLIR"; 618abd95342SNiranjan Hasabnis 619abd95342SNiranjan Hasabnis DialectRegistry registry; 620abd95342SNiranjan Hasabnis registry.insert<DLTIDialect, DLTargetSystemDescTestDialect>(); 621abd95342SNiranjan Hasabnis MLIRContext ctx(registry); 622abd95342SNiranjan Hasabnis 623abd95342SNiranjan Hasabnis OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx); 624abd95342SNiranjan Hasabnis DataLayout layout(*module); 625bdeee9b1SNiranjan Hasabnis EXPECT_EQ(layout.getDevicePropertyValue( 626abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("CPU") /* device ID*/, 627abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("L1_cache_size_in_bytes")), 628bdeee9b1SNiranjan Hasabnis std::optional<Attribute>(Builder(&ctx).getStringAttr("4096"))); 629bdeee9b1SNiranjan Hasabnis EXPECT_EQ(layout.getDevicePropertyValue( 630abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("CPU") /* device ID*/, 631abd95342SNiranjan Hasabnis Builder(&ctx).getStringAttr("max_vector_op_width")), 632bdeee9b1SNiranjan Hasabnis std::optional<Attribute>(Builder(&ctx).getStringAttr("128"))); 633abd95342SNiranjan Hasabnis } 634abd95342SNiranjan Hasabnis 6353ba14fa0SAlex Zinenko TEST(DataLayout, Caching) { 6363ba14fa0SAlex Zinenko const char *ir = R"MLIR( 6373ba14fa0SAlex Zinenko "dltest.op_with_layout"() { dltest.layout = #dltest.spec<> } : () -> () 6383ba14fa0SAlex Zinenko )MLIR"; 6393ba14fa0SAlex Zinenko 6403ba14fa0SAlex Zinenko DialectRegistry registry; 6413ba14fa0SAlex Zinenko registry.insert<DLTIDialect, DLTestDialect>(); 6423ba14fa0SAlex Zinenko MLIRContext ctx(registry); 6433ba14fa0SAlex Zinenko 644dfaadf6bSChristian Sigg OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx); 6453ba14fa0SAlex Zinenko auto op = 6463ba14fa0SAlex Zinenko cast<DataLayoutOpInterface>(module->getBody()->getOperations().front()); 6473ba14fa0SAlex Zinenko DataLayout layout(op); 6483ba14fa0SAlex Zinenko 6493ba14fa0SAlex Zinenko unsigned sum = 0; 6503ba14fa0SAlex Zinenko sum += layout.getTypeSize(SingleQueryType::get(&ctx)); 6513ba14fa0SAlex Zinenko // The second call should hit the cache. If it does not, the function in 6523ba14fa0SAlex Zinenko // SingleQueryType will be called and will abort the process. 6533ba14fa0SAlex Zinenko sum += layout.getTypeSize(SingleQueryType::get(&ctx)); 6543ba14fa0SAlex Zinenko // Make sure the complier doesn't optimize away the query code. 6553ba14fa0SAlex Zinenko EXPECT_EQ(sum, 2u); 6563ba14fa0SAlex Zinenko 6573ba14fa0SAlex Zinenko // A fresh data layout has a new cache, so the call to it should be dispatched 65857035192SEymen Ünay // down to the type and abort the process. 6593ba14fa0SAlex Zinenko DataLayout second(op); 6603ba14fa0SAlex Zinenko ASSERT_DEATH(second.getTypeSize(SingleQueryType::get(&ctx)), "repeated call"); 6613ba14fa0SAlex Zinenko } 6623ba14fa0SAlex Zinenko 6633ba14fa0SAlex Zinenko TEST(DataLayout, CacheInvalidation) { 6643ba14fa0SAlex Zinenko const char *ir = R"MLIR( 6653ba14fa0SAlex Zinenko "dltest.op_with_layout"() { dltest.layout = #dltest.spec< 6663ba14fa0SAlex Zinenko #dlti.dl_entry<i42, 5>, 6673ba14fa0SAlex Zinenko #dlti.dl_entry<i16, 6> 6683ba14fa0SAlex Zinenko > } : () -> () 6693ba14fa0SAlex Zinenko )MLIR"; 6703ba14fa0SAlex Zinenko 6713ba14fa0SAlex Zinenko DialectRegistry registry; 6723ba14fa0SAlex Zinenko registry.insert<DLTIDialect, DLTestDialect>(); 6733ba14fa0SAlex Zinenko MLIRContext ctx(registry); 6743ba14fa0SAlex Zinenko 675dfaadf6bSChristian Sigg OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx); 6763ba14fa0SAlex Zinenko auto op = 6773ba14fa0SAlex Zinenko cast<DataLayoutOpInterface>(module->getBody()->getOperations().front()); 6783ba14fa0SAlex Zinenko DataLayout layout(op); 6793ba14fa0SAlex Zinenko 6803ba14fa0SAlex Zinenko // Normal query is fine. 6813ba14fa0SAlex Zinenko EXPECT_EQ(layout.getTypeSize(Float16Type::get(&ctx)), 6u); 6823ba14fa0SAlex Zinenko 6833ba14fa0SAlex Zinenko // Replace the data layout spec with a new, empty spec. 6843ba14fa0SAlex Zinenko op->setAttr(kAttrName, CustomDataLayoutSpec::get(&ctx, {})); 6853ba14fa0SAlex Zinenko 6863ba14fa0SAlex Zinenko // Data layout is no longer valid and should trigger assertion when queried. 6873ba14fa0SAlex Zinenko #ifndef NDEBUG 6883ba14fa0SAlex Zinenko ASSERT_DEATH(layout.getTypeSize(Float16Type::get(&ctx)), "no longer valid"); 6893ba14fa0SAlex Zinenko #endif 6903ba14fa0SAlex Zinenko } 6913ba14fa0SAlex Zinenko 6923ba14fa0SAlex Zinenko TEST(DataLayout, UnimplementedTypeInterface) { 6933ba14fa0SAlex Zinenko const char *ir = R"MLIR( 6943ba14fa0SAlex Zinenko "dltest.op_with_layout"() { dltest.layout = #dltest.spec<> } : () -> () 6953ba14fa0SAlex Zinenko )MLIR"; 6963ba14fa0SAlex Zinenko 6973ba14fa0SAlex Zinenko DialectRegistry registry; 6983ba14fa0SAlex Zinenko registry.insert<DLTIDialect, DLTestDialect>(); 6993ba14fa0SAlex Zinenko MLIRContext ctx(registry); 7003ba14fa0SAlex Zinenko 701dfaadf6bSChristian Sigg OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx); 7023ba14fa0SAlex Zinenko auto op = 7033ba14fa0SAlex Zinenko cast<DataLayoutOpInterface>(module->getBody()->getOperations().front()); 7043ba14fa0SAlex Zinenko DataLayout layout(op); 7053ba14fa0SAlex Zinenko 7063ba14fa0SAlex Zinenko ASSERT_DEATH(layout.getTypeSize(TypeNoLayout::get(&ctx)), 7073ba14fa0SAlex Zinenko "neither the scoping op nor the type class provide data layout " 7083ba14fa0SAlex Zinenko "information"); 7093ba14fa0SAlex Zinenko } 710f9cdc61dSAlex Zinenko 711f9cdc61dSAlex Zinenko TEST(DataLayout, SevenBitByte) { 712f9cdc61dSAlex Zinenko const char *ir = R"MLIR( 713f9cdc61dSAlex Zinenko "dltest.op_with_7bit_byte"() { dltest.layout = #dltest.spec<> } : () -> () 714f9cdc61dSAlex Zinenko )MLIR"; 715f9cdc61dSAlex Zinenko 716f9cdc61dSAlex Zinenko DialectRegistry registry; 717f9cdc61dSAlex Zinenko registry.insert<DLTIDialect, DLTestDialect>(); 718f9cdc61dSAlex Zinenko MLIRContext ctx(registry); 719f9cdc61dSAlex Zinenko 720dfaadf6bSChristian Sigg OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx); 721f9cdc61dSAlex Zinenko auto op = 722f9cdc61dSAlex Zinenko cast<DataLayoutOpInterface>(module->getBody()->getOperations().front()); 723f9cdc61dSAlex Zinenko DataLayout layout(op); 724f9cdc61dSAlex Zinenko 725f9cdc61dSAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(IntegerType::get(&ctx, 42)), 42u); 726f9cdc61dSAlex Zinenko EXPECT_EQ(layout.getTypeSizeInBits(IntegerType::get(&ctx, 32)), 32u); 727f9cdc61dSAlex Zinenko EXPECT_EQ(layout.getTypeSize(IntegerType::get(&ctx, 42)), 6u); 728f9cdc61dSAlex Zinenko EXPECT_EQ(layout.getTypeSize(IntegerType::get(&ctx, 32)), 5u); 729f9cdc61dSAlex Zinenko } 730