diff options
author | Christian Ulmann <christianulmann@gmail.com> | 2024-04-03 14:54:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-03 14:54:29 +0200 |
commit | a2acf3132334e3131ec584c2c54ec5ba2214e074 (patch) | |
tree | 6d010f476951943b5fa0bdc214be01b316154dce | |
parent | 7ec87c473936245ea11f8bb64c936e5112f25e6a (diff) | |
download | llvm-a2acf3132334e3131ec584c2c54ec5ba2214e074.zip llvm-a2acf3132334e3131ec584c2c54ec5ba2214e074.tar.gz llvm-a2acf3132334e3131ec584c2c54ec5ba2214e074.tar.bz2 |
[MLIR] Add endianness accessors to the data layout (#87347)
This commit extends the data layout subsystem with accessors for the
endianness. The implementation follows the structure implemented for
alloca, global, and program memory spaces.
-rw-r--r-- | mlir/include/mlir/Dialect/DLTI/DLTI.h | 3 | ||||
-rw-r--r-- | mlir/include/mlir/Interfaces/DataLayoutInterfaces.h | 9 | ||||
-rw-r--r-- | mlir/include/mlir/Interfaces/DataLayoutInterfaces.td | 18 | ||||
-rw-r--r-- | mlir/lib/Dialect/DLTI/DLTI.cpp | 5 | ||||
-rw-r--r-- | mlir/lib/Interfaces/DataLayoutInterfaces.cpp | 25 | ||||
-rw-r--r-- | mlir/test/Dialect/LLVMIR/layout.mlir | 8 | ||||
-rw-r--r-- | mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp | 4 | ||||
-rw-r--r-- | mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp | 18 |
8 files changed, 90 insertions, 0 deletions
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTI.h b/mlir/include/mlir/Dialect/DLTI/DLTI.h index bf23aa2..5ac7c11 100644 --- a/mlir/include/mlir/Dialect/DLTI/DLTI.h +++ b/mlir/include/mlir/Dialect/DLTI/DLTI.h @@ -100,6 +100,9 @@ public: /// Returns the list of entries. DataLayoutEntryListRef getEntries() const; + /// Returns the endiannes identifier. + StringAttr getEndiannessIdentifier(MLIRContext *context) const; + /// Returns the alloca memory space identifier. StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const; diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h index 0463546..76bf33e 100644 --- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h +++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h @@ -64,6 +64,10 @@ std::optional<uint64_t> getDefaultIndexBitwidth(Type type, const DataLayout &dataLayout, ArrayRef<DataLayoutEntryInterface> params); +/// Default handler for endianness request. Dispatches to the +/// DataLayoutInterface if specified, otherwise returns the default. +Attribute getDefaultEndianness(DataLayoutEntryInterface entry); + /// Default handler for alloca memory space request. Dispatches to the /// DataLayoutInterface if specified, otherwise returns the default. Attribute getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry); @@ -192,6 +196,9 @@ public: /// type is not a pointer-like type, it returns std::nullopt. std::optional<uint64_t> getTypeIndexBitwidth(Type t) const; + /// Returns the specified endianness. + Attribute getEndianness() const; + /// Returns the memory space used for AllocaOps. Attribute getAllocaMemorySpace() const; @@ -230,6 +237,8 @@ private: mutable DenseMap<Type, uint64_t> preferredAlignments; mutable DenseMap<Type, std::optional<uint64_t>> indexBitwidths; + /// Cache for the endianness. + mutable std::optional<Attribute> endianness; /// Cache for alloca, global, and program memory spaces. mutable std::optional<Attribute> allocaMemorySpace; mutable std::optional<Attribute> programMemorySpace; diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td index 0ee7a11..9edc885 100644 --- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td +++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td @@ -107,6 +107,12 @@ def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface"> { /*args=*/(ins) >, InterfaceMethod< + /*description=*/"Returns the endianness identifier.", + /*retTy=*/"::mlir::StringAttr", + /*methodName=*/"getEndiannessIdentifier", + /*args=*/(ins "::mlir::MLIRContext *":$context) + >, + InterfaceMethod< /*description=*/"Returns the alloca memory space identifier.", /*retTy=*/"::mlir::StringAttr", /*methodName=*/"getAllocaMemorySpaceIdentifier", @@ -297,6 +303,18 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> { }] >, StaticInterfaceMethod< + /*description=*/"Returns the endianness used by the ABI computed " + "using the relevant entries. The data layout object " + "can be used for recursive queries.", + /*retTy=*/"::mlir::Attribute", + /*methodName=*/"getEndianness", + /*args=*/(ins "::mlir::DataLayoutEntryInterface":$entry), + /*methodBody=*/"", + /*defaultImplementation=*/[{ + return ::mlir::detail::getDefaultEndianness(entry); + }] + >, + StaticInterfaceMethod< /*description=*/"Returns the memory space used by the ABI computed " "using the relevant entries. The data layout object " "can be used for recursive queries.", diff --git a/mlir/lib/Dialect/DLTI/DLTI.cpp b/mlir/lib/Dialect/DLTI/DLTI.cpp index daef234..98a8865 100644 --- a/mlir/lib/Dialect/DLTI/DLTI.cpp +++ b/mlir/lib/Dialect/DLTI/DLTI.cpp @@ -282,6 +282,11 @@ DataLayoutEntryListRef DataLayoutSpecAttr::getEntries() const { } StringAttr +DataLayoutSpecAttr::getEndiannessIdentifier(MLIRContext *context) const { + return Builder(context).getStringAttr(DLTIDialect::kDataLayoutEndiannessKey); +} + +StringAttr DataLayoutSpecAttr::getAllocaMemorySpaceIdentifier(MLIRContext *context) const { return Builder(context).getStringAttr( DLTIDialect::kDataLayoutAllocaMemorySpaceKey); diff --git a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp index b5b7d78..e93a9ef 100644 --- a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp +++ b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp @@ -234,6 +234,15 @@ std::optional<uint64_t> mlir::detail::getDefaultIndexBitwidth( return std::nullopt; } +// Returns the endianness if specified in the given entry. If the entry is empty +// the default endianness represented by an empty attribute is returned. +Attribute mlir::detail::getDefaultEndianness(DataLayoutEntryInterface entry) { + if (entry == DataLayoutEntryInterface()) + return Attribute(); + + return entry.getValue(); +} + // Returns the memory space used for alloca operations if specified in the // given entry. If the entry is empty the default memory space represented by // an empty attribute is returned. @@ -548,6 +557,22 @@ std::optional<uint64_t> mlir::DataLayout::getTypeIndexBitwidth(Type t) const { }); } +mlir::Attribute mlir::DataLayout::getEndianness() const { + checkValid(); + if (endianness) + return *endianness; + DataLayoutEntryInterface entry; + if (originalLayout) + entry = originalLayout.getSpecForIdentifier( + originalLayout.getEndiannessIdentifier(originalLayout.getContext())); + + if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope)) + endianness = iface.getEndianness(entry); + else + endianness = detail::getDefaultEndianness(entry); + return *endianness; +} + mlir::Attribute mlir::DataLayout::getAllocaMemorySpace() const { checkValid(); if (allocaMemorySpace) diff --git a/mlir/test/Dialect/LLVMIR/layout.mlir b/mlir/test/Dialect/LLVMIR/layout.mlir index a78fb77..4813089 100644 --- a/mlir/test/Dialect/LLVMIR/layout.mlir +++ b/mlir/test/Dialect/LLVMIR/layout.mlir @@ -6,6 +6,7 @@ module { // CHECK: alignment = 8 // CHECK: alloca_memory_space = 0 // CHECK: bitsize = 64 + // CHECK: endianness = "" // CHECK: global_memory_space = 0 // CHECK: index = 64 // CHECK: preferred = 8 @@ -16,6 +17,7 @@ module { // CHECK: alignment = 8 // CHECK: alloca_memory_space = 0 // CHECK: bitsize = 64 + // CHECK: endianness = "" // CHECK: global_memory_space = 0 // CHECK: index = 64 // CHECK: preferred = 8 @@ -26,6 +28,7 @@ module { // CHECK: alignment = 8 // CHECK: alloca_memory_space = 0 // CHECK: bitsize = 64 + // CHECK: endianness = "" // CHECK: global_memory_space = 0 // CHECK: index = 64 // CHECK: preferred = 8 @@ -43,6 +46,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry<!llvm.ptr, dense<[32, 32, 64]> : vector<3xi64>>, #dlti.dl_entry<!llvm.ptr<5>, dense<[64, 64, 64]> : vector<3xi64>>, #dlti.dl_entry<!llvm.ptr<4>, dense<[32, 64, 64, 24]> : vector<4xi64>>, + #dlti.dl_entry<"dlti.endianness", "little">, #dlti.dl_entry<"dlti.alloca_memory_space", 5 : ui64>, #dlti.dl_entry<"dlti.global_memory_space", 2 : ui64>, #dlti.dl_entry<"dlti.program_memory_space", 3 : ui64>, @@ -53,6 +57,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< // CHECK: alignment = 4 // CHECK: alloca_memory_space = 5 // CHECK: bitsize = 32 + // CHECK: endianness = "little" // CHECK: global_memory_space = 2 // CHECK: index = 32 // CHECK: preferred = 8 @@ -63,6 +68,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< // CHECK: alignment = 4 // CHECK: alloca_memory_space = 5 // CHECK: bitsize = 32 + // CHECK: endianness = "little" // CHECK: global_memory_space = 2 // CHECK: index = 32 // CHECK: preferred = 8 @@ -73,6 +79,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< // CHECK: alignment = 8 // CHECK: alloca_memory_space = 5 // CHECK: bitsize = 64 + // CHECK: endianness = "little" // CHECK: global_memory_space = 2 // CHECK: index = 64 // CHECK: preferred = 8 @@ -83,6 +90,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< // CHECK: alignment = 8 // CHECK: alloca_memory_space = 5 // CHECK: bitsize = 32 + // CHECK: endianness = "little" // CHECK: global_memory_space = 2 // CHECK: index = 24 // CHECK: preferred = 8 diff --git a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp index 3da48ff..a4464bb 100644 --- a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp +++ b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp @@ -41,6 +41,7 @@ struct TestDataLayoutQuery uint64_t alignment = layout.getTypeABIAlignment(op.getType()); uint64_t preferred = layout.getTypePreferredAlignment(op.getType()); uint64_t index = layout.getTypeIndexBitwidth(op.getType()).value_or(0); + Attribute endianness = layout.getEndianness(); Attribute allocaMemorySpace = layout.getAllocaMemorySpace(); Attribute programMemorySpace = layout.getProgramMemorySpace(); Attribute globalMemorySpace = layout.getGlobalMemorySpace(); @@ -51,6 +52,9 @@ struct TestDataLayoutQuery builder.getNamedAttr("alignment", builder.getIndexAttr(alignment)), builder.getNamedAttr("preferred", builder.getIndexAttr(preferred)), builder.getNamedAttr("index", builder.getIndexAttr(index)), + builder.getNamedAttr("endianness", endianness == Attribute() + ? builder.getStringAttr("") + : endianness), builder.getNamedAttr("alloca_memory_space", allocaMemorySpace == Attribute() ? builder.getUI32IntegerAttr(0) diff --git a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp index d6b8d73..5f48429 100644 --- a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp +++ b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp @@ -22,6 +22,7 @@ using namespace mlir; namespace { constexpr static llvm::StringLiteral kAttrName = "dltest.layout"; +constexpr static llvm::StringLiteral kEndiannesKeyName = "dltest.endianness"; constexpr static llvm::StringLiteral kAllocaKeyName = "dltest.alloca_memory_space"; constexpr static llvm::StringLiteral kProgramKeyName = @@ -73,6 +74,9 @@ struct CustomDataLayoutSpec } DataLayoutEntryListRef getEntries() const { return getImpl()->entries; } LogicalResult verifySpec(Location loc) { return success(); } + StringAttr getEndiannessIdentifier(MLIRContext *context) const { + return Builder(context).getStringAttr(kEndiannesKeyName); + } StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const { return Builder(context).getStringAttr(kAllocaKeyName); } @@ -130,6 +134,15 @@ struct SingleQueryType return 4; } + Attribute getEndianness(DataLayoutEntryInterface entry) { + static bool executed = false; + if (executed) + llvm::report_fatal_error("repeated call"); + + executed = true; + return Attribute(); + } + Attribute getAllocaMemorySpace(DataLayoutEntryInterface entry) { static bool executed = false; if (executed) @@ -317,6 +330,7 @@ module {} EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 42)), 8u); EXPECT_EQ(layout.getTypePreferredAlignment(Float16Type::get(&ctx)), 2u); + EXPECT_EQ(layout.getEndianness(), Attribute()); EXPECT_EQ(layout.getAllocaMemorySpace(), Attribute()); EXPECT_EQ(layout.getProgramMemorySpace(), Attribute()); EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute()); @@ -348,6 +362,7 @@ TEST(DataLayout, NullSpec) { EXPECT_EQ(layout.getTypeIndexBitwidth(Float16Type::get(&ctx)), std::nullopt); EXPECT_EQ(layout.getTypeIndexBitwidth(IndexType::get(&ctx)), 64u); + EXPECT_EQ(layout.getEndianness(), Attribute()); EXPECT_EQ(layout.getAllocaMemorySpace(), Attribute()); EXPECT_EQ(layout.getProgramMemorySpace(), Attribute()); EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute()); @@ -378,6 +393,7 @@ TEST(DataLayout, EmptySpec) { EXPECT_EQ(layout.getTypeIndexBitwidth(Float16Type::get(&ctx)), std::nullopt); EXPECT_EQ(layout.getTypeIndexBitwidth(IndexType::get(&ctx)), 64u); + EXPECT_EQ(layout.getEndianness(), Attribute()); EXPECT_EQ(layout.getAllocaMemorySpace(), Attribute()); EXPECT_EQ(layout.getProgramMemorySpace(), Attribute()); EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute()); @@ -390,6 +406,7 @@ TEST(DataLayout, SpecWithEntries) { #dlti.dl_entry<i42, 5>, #dlti.dl_entry<i16, 6>, #dlti.dl_entry<index, 42>, + #dlti.dl_entry<"dltest.endianness", "little">, #dlti.dl_entry<"dltest.alloca_memory_space", 5 : i32>, #dlti.dl_entry<"dltest.program_memory_space", 3 : i32>, #dlti.dl_entry<"dltest.global_memory_space", 2 : i32>, @@ -425,6 +442,7 @@ TEST(DataLayout, SpecWithEntries) { EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 32)), 64u); EXPECT_EQ(layout.getTypePreferredAlignment(Float32Type::get(&ctx)), 64u); + EXPECT_EQ(layout.getEndianness(), Builder(&ctx).getStringAttr("little")); EXPECT_EQ(layout.getAllocaMemorySpace(), Builder(&ctx).getI32IntegerAttr(5)); EXPECT_EQ(layout.getProgramMemorySpace(), Builder(&ctx).getI32IntegerAttr(3)); EXPECT_EQ(layout.getGlobalMemorySpace(), Builder(&ctx).getI32IntegerAttr(2)); |