Skip to content

Commit a2acf31

Browse files
authored
[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.
1 parent 7ec87c4 commit a2acf31

File tree

8 files changed

+90
-0
lines changed

8 files changed

+90
-0
lines changed

mlir/include/mlir/Dialect/DLTI/DLTI.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ class DataLayoutSpecAttr
100100
/// Returns the list of entries.
101101
DataLayoutEntryListRef getEntries() const;
102102

103+
/// Returns the endiannes identifier.
104+
StringAttr getEndiannessIdentifier(MLIRContext *context) const;
105+
103106
/// Returns the alloca memory space identifier.
104107
StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const;
105108

mlir/include/mlir/Interfaces/DataLayoutInterfaces.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ std::optional<uint64_t>
6464
getDefaultIndexBitwidth(Type type, const DataLayout &dataLayout,
6565
ArrayRef<DataLayoutEntryInterface> params);
6666

67+
/// Default handler for endianness request. Dispatches to the
68+
/// DataLayoutInterface if specified, otherwise returns the default.
69+
Attribute getDefaultEndianness(DataLayoutEntryInterface entry);
70+
6771
/// Default handler for alloca memory space request. Dispatches to the
6872
/// DataLayoutInterface if specified, otherwise returns the default.
6973
Attribute getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry);
@@ -192,6 +196,9 @@ class DataLayout {
192196
/// type is not a pointer-like type, it returns std::nullopt.
193197
std::optional<uint64_t> getTypeIndexBitwidth(Type t) const;
194198

199+
/// Returns the specified endianness.
200+
Attribute getEndianness() const;
201+
195202
/// Returns the memory space used for AllocaOps.
196203
Attribute getAllocaMemorySpace() const;
197204

@@ -230,6 +237,8 @@ class DataLayout {
230237
mutable DenseMap<Type, uint64_t> preferredAlignments;
231238
mutable DenseMap<Type, std::optional<uint64_t>> indexBitwidths;
232239

240+
/// Cache for the endianness.
241+
mutable std::optional<Attribute> endianness;
233242
/// Cache for alloca, global, and program memory spaces.
234243
mutable std::optional<Attribute> allocaMemorySpace;
235244
mutable std::optional<Attribute> programMemorySpace;

mlir/include/mlir/Interfaces/DataLayoutInterfaces.td

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface"> {
106106
/*methodName=*/"getEntries",
107107
/*args=*/(ins)
108108
>,
109+
InterfaceMethod<
110+
/*description=*/"Returns the endianness identifier.",
111+
/*retTy=*/"::mlir::StringAttr",
112+
/*methodName=*/"getEndiannessIdentifier",
113+
/*args=*/(ins "::mlir::MLIRContext *":$context)
114+
>,
109115
InterfaceMethod<
110116
/*description=*/"Returns the alloca memory space identifier.",
111117
/*retTy=*/"::mlir::StringAttr",
@@ -296,6 +302,18 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> {
296302
params);
297303
}]
298304
>,
305+
StaticInterfaceMethod<
306+
/*description=*/"Returns the endianness used by the ABI computed "
307+
"using the relevant entries. The data layout object "
308+
"can be used for recursive queries.",
309+
/*retTy=*/"::mlir::Attribute",
310+
/*methodName=*/"getEndianness",
311+
/*args=*/(ins "::mlir::DataLayoutEntryInterface":$entry),
312+
/*methodBody=*/"",
313+
/*defaultImplementation=*/[{
314+
return ::mlir::detail::getDefaultEndianness(entry);
315+
}]
316+
>,
299317
StaticInterfaceMethod<
300318
/*description=*/"Returns the memory space used by the ABI computed "
301319
"using the relevant entries. The data layout object "

mlir/lib/Dialect/DLTI/DLTI.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,11 @@ DataLayoutEntryListRef DataLayoutSpecAttr::getEntries() const {
281281
return getImpl()->entries;
282282
}
283283

284+
StringAttr
285+
DataLayoutSpecAttr::getEndiannessIdentifier(MLIRContext *context) const {
286+
return Builder(context).getStringAttr(DLTIDialect::kDataLayoutEndiannessKey);
287+
}
288+
284289
StringAttr
285290
DataLayoutSpecAttr::getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
286291
return Builder(context).getStringAttr(

mlir/lib/Interfaces/DataLayoutInterfaces.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,15 @@ std::optional<uint64_t> mlir::detail::getDefaultIndexBitwidth(
234234
return std::nullopt;
235235
}
236236

237+
// Returns the endianness if specified in the given entry. If the entry is empty
238+
// the default endianness represented by an empty attribute is returned.
239+
Attribute mlir::detail::getDefaultEndianness(DataLayoutEntryInterface entry) {
240+
if (entry == DataLayoutEntryInterface())
241+
return Attribute();
242+
243+
return entry.getValue();
244+
}
245+
237246
// Returns the memory space used for alloca operations if specified in the
238247
// given entry. If the entry is empty the default memory space represented by
239248
// an empty attribute is returned.
@@ -548,6 +557,22 @@ std::optional<uint64_t> mlir::DataLayout::getTypeIndexBitwidth(Type t) const {
548557
});
549558
}
550559

560+
mlir::Attribute mlir::DataLayout::getEndianness() const {
561+
checkValid();
562+
if (endianness)
563+
return *endianness;
564+
DataLayoutEntryInterface entry;
565+
if (originalLayout)
566+
entry = originalLayout.getSpecForIdentifier(
567+
originalLayout.getEndiannessIdentifier(originalLayout.getContext()));
568+
569+
if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
570+
endianness = iface.getEndianness(entry);
571+
else
572+
endianness = detail::getDefaultEndianness(entry);
573+
return *endianness;
574+
}
575+
551576
mlir::Attribute mlir::DataLayout::getAllocaMemorySpace() const {
552577
checkValid();
553578
if (allocaMemorySpace)

mlir/test/Dialect/LLVMIR/layout.mlir

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module {
66
// CHECK: alignment = 8
77
// CHECK: alloca_memory_space = 0
88
// CHECK: bitsize = 64
9+
// CHECK: endianness = ""
910
// CHECK: global_memory_space = 0
1011
// CHECK: index = 64
1112
// CHECK: preferred = 8
@@ -16,6 +17,7 @@ module {
1617
// CHECK: alignment = 8
1718
// CHECK: alloca_memory_space = 0
1819
// CHECK: bitsize = 64
20+
// CHECK: endianness = ""
1921
// CHECK: global_memory_space = 0
2022
// CHECK: index = 64
2123
// CHECK: preferred = 8
@@ -26,6 +28,7 @@ module {
2628
// CHECK: alignment = 8
2729
// CHECK: alloca_memory_space = 0
2830
// CHECK: bitsize = 64
31+
// CHECK: endianness = ""
2932
// CHECK: global_memory_space = 0
3033
// CHECK: index = 64
3134
// CHECK: preferred = 8
@@ -43,6 +46,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
4346
#dlti.dl_entry<!llvm.ptr, dense<[32, 32, 64]> : vector<3xi64>>,
4447
#dlti.dl_entry<!llvm.ptr<5>, dense<[64, 64, 64]> : vector<3xi64>>,
4548
#dlti.dl_entry<!llvm.ptr<4>, dense<[32, 64, 64, 24]> : vector<4xi64>>,
49+
#dlti.dl_entry<"dlti.endianness", "little">,
4650
#dlti.dl_entry<"dlti.alloca_memory_space", 5 : ui64>,
4751
#dlti.dl_entry<"dlti.global_memory_space", 2 : ui64>,
4852
#dlti.dl_entry<"dlti.program_memory_space", 3 : ui64>,
@@ -53,6 +57,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
5357
// CHECK: alignment = 4
5458
// CHECK: alloca_memory_space = 5
5559
// CHECK: bitsize = 32
60+
// CHECK: endianness = "little"
5661
// CHECK: global_memory_space = 2
5762
// CHECK: index = 32
5863
// CHECK: preferred = 8
@@ -63,6 +68,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
6368
// CHECK: alignment = 4
6469
// CHECK: alloca_memory_space = 5
6570
// CHECK: bitsize = 32
71+
// CHECK: endianness = "little"
6672
// CHECK: global_memory_space = 2
6773
// CHECK: index = 32
6874
// CHECK: preferred = 8
@@ -73,6 +79,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
7379
// CHECK: alignment = 8
7480
// CHECK: alloca_memory_space = 5
7581
// CHECK: bitsize = 64
82+
// CHECK: endianness = "little"
7683
// CHECK: global_memory_space = 2
7784
// CHECK: index = 64
7885
// CHECK: preferred = 8
@@ -83,6 +90,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
8390
// CHECK: alignment = 8
8491
// CHECK: alloca_memory_space = 5
8592
// CHECK: bitsize = 32
93+
// CHECK: endianness = "little"
8694
// CHECK: global_memory_space = 2
8795
// CHECK: index = 24
8896
// CHECK: preferred = 8

mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct TestDataLayoutQuery
4141
uint64_t alignment = layout.getTypeABIAlignment(op.getType());
4242
uint64_t preferred = layout.getTypePreferredAlignment(op.getType());
4343
uint64_t index = layout.getTypeIndexBitwidth(op.getType()).value_or(0);
44+
Attribute endianness = layout.getEndianness();
4445
Attribute allocaMemorySpace = layout.getAllocaMemorySpace();
4546
Attribute programMemorySpace = layout.getProgramMemorySpace();
4647
Attribute globalMemorySpace = layout.getGlobalMemorySpace();
@@ -51,6 +52,9 @@ struct TestDataLayoutQuery
5152
builder.getNamedAttr("alignment", builder.getIndexAttr(alignment)),
5253
builder.getNamedAttr("preferred", builder.getIndexAttr(preferred)),
5354
builder.getNamedAttr("index", builder.getIndexAttr(index)),
55+
builder.getNamedAttr("endianness", endianness == Attribute()
56+
? builder.getStringAttr("")
57+
: endianness),
5458
builder.getNamedAttr("alloca_memory_space",
5559
allocaMemorySpace == Attribute()
5660
? builder.getUI32IntegerAttr(0)

mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ using namespace mlir;
2222

2323
namespace {
2424
constexpr static llvm::StringLiteral kAttrName = "dltest.layout";
25+
constexpr static llvm::StringLiteral kEndiannesKeyName = "dltest.endianness";
2526
constexpr static llvm::StringLiteral kAllocaKeyName =
2627
"dltest.alloca_memory_space";
2728
constexpr static llvm::StringLiteral kProgramKeyName =
@@ -73,6 +74,9 @@ struct CustomDataLayoutSpec
7374
}
7475
DataLayoutEntryListRef getEntries() const { return getImpl()->entries; }
7576
LogicalResult verifySpec(Location loc) { return success(); }
77+
StringAttr getEndiannessIdentifier(MLIRContext *context) const {
78+
return Builder(context).getStringAttr(kEndiannesKeyName);
79+
}
7680
StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
7781
return Builder(context).getStringAttr(kAllocaKeyName);
7882
}
@@ -130,6 +134,15 @@ struct SingleQueryType
130134
return 4;
131135
}
132136

137+
Attribute getEndianness(DataLayoutEntryInterface entry) {
138+
static bool executed = false;
139+
if (executed)
140+
llvm::report_fatal_error("repeated call");
141+
142+
executed = true;
143+
return Attribute();
144+
}
145+
133146
Attribute getAllocaMemorySpace(DataLayoutEntryInterface entry) {
134147
static bool executed = false;
135148
if (executed)
@@ -317,6 +330,7 @@ module {}
317330
EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 42)), 8u);
318331
EXPECT_EQ(layout.getTypePreferredAlignment(Float16Type::get(&ctx)), 2u);
319332

333+
EXPECT_EQ(layout.getEndianness(), Attribute());
320334
EXPECT_EQ(layout.getAllocaMemorySpace(), Attribute());
321335
EXPECT_EQ(layout.getProgramMemorySpace(), Attribute());
322336
EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute());
@@ -348,6 +362,7 @@ TEST(DataLayout, NullSpec) {
348362
EXPECT_EQ(layout.getTypeIndexBitwidth(Float16Type::get(&ctx)), std::nullopt);
349363
EXPECT_EQ(layout.getTypeIndexBitwidth(IndexType::get(&ctx)), 64u);
350364

365+
EXPECT_EQ(layout.getEndianness(), Attribute());
351366
EXPECT_EQ(layout.getAllocaMemorySpace(), Attribute());
352367
EXPECT_EQ(layout.getProgramMemorySpace(), Attribute());
353368
EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute());
@@ -378,6 +393,7 @@ TEST(DataLayout, EmptySpec) {
378393
EXPECT_EQ(layout.getTypeIndexBitwidth(Float16Type::get(&ctx)), std::nullopt);
379394
EXPECT_EQ(layout.getTypeIndexBitwidth(IndexType::get(&ctx)), 64u);
380395

396+
EXPECT_EQ(layout.getEndianness(), Attribute());
381397
EXPECT_EQ(layout.getAllocaMemorySpace(), Attribute());
382398
EXPECT_EQ(layout.getProgramMemorySpace(), Attribute());
383399
EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute());
@@ -390,6 +406,7 @@ TEST(DataLayout, SpecWithEntries) {
390406
#dlti.dl_entry<i42, 5>,
391407
#dlti.dl_entry<i16, 6>,
392408
#dlti.dl_entry<index, 42>,
409+
#dlti.dl_entry<"dltest.endianness", "little">,
393410
#dlti.dl_entry<"dltest.alloca_memory_space", 5 : i32>,
394411
#dlti.dl_entry<"dltest.program_memory_space", 3 : i32>,
395412
#dlti.dl_entry<"dltest.global_memory_space", 2 : i32>,
@@ -425,6 +442,7 @@ TEST(DataLayout, SpecWithEntries) {
425442
EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 32)), 64u);
426443
EXPECT_EQ(layout.getTypePreferredAlignment(Float32Type::get(&ctx)), 64u);
427444

445+
EXPECT_EQ(layout.getEndianness(), Builder(&ctx).getStringAttr("little"));
428446
EXPECT_EQ(layout.getAllocaMemorySpace(), Builder(&ctx).getI32IntegerAttr(5));
429447
EXPECT_EQ(layout.getProgramMemorySpace(), Builder(&ctx).getI32IntegerAttr(3));
430448
EXPECT_EQ(layout.getGlobalMemorySpace(), Builder(&ctx).getI32IntegerAttr(2));

0 commit comments

Comments
 (0)