xref: /llvm-project/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp (revision 5c1752e368585e55c0335a7d7651fe43d42af282)
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