aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Ulmann <christianulmann@gmail.com>2024-04-03 14:54:29 +0200
committerGitHub <noreply@github.com>2024-04-03 14:54:29 +0200
commita2acf3132334e3131ec584c2c54ec5ba2214e074 (patch)
tree6d010f476951943b5fa0bdc214be01b316154dce
parent7ec87c473936245ea11f8bb64c936e5112f25e6a (diff)
downloadllvm-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.h3
-rw-r--r--mlir/include/mlir/Interfaces/DataLayoutInterfaces.h9
-rw-r--r--mlir/include/mlir/Interfaces/DataLayoutInterfaces.td18
-rw-r--r--mlir/lib/Dialect/DLTI/DLTI.cpp5
-rw-r--r--mlir/lib/Interfaces/DataLayoutInterfaces.cpp25
-rw-r--r--mlir/test/Dialect/LLVMIR/layout.mlir8
-rw-r--r--mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp4
-rw-r--r--mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp18
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));