Skip to content

Commit 382eb7c

Browse files
committed
[mlir] Add alloca address space handling to the data layout subsystem
This patch adds alloca address space information to the data layout interface and implementation in the DLTI dialect. This is needed for targets that use separate address spaces for local/stack data. Reviewed By: ftynse, krzysz00 Differential Revision: https://reviews.llvm.org/D144657
1 parent 8022ff5 commit 382eb7c

File tree

11 files changed

+155
-9
lines changed

11 files changed

+155
-9
lines changed

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

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

101+
/// Returns the alloca memory space identifier.
102+
StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const;
103+
101104
/// Parses an instance of this attribute.
102105
static DataLayoutSpecAttr parse(AsmParser &parser);
103106

mlir/include/mlir/Dialect/DLTI/DLTIBase.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ def DLTI_Dialect : Dialect {
2323
}];
2424

2525
let extraClassDeclaration = [{
26+
// Top level attribute name.
2627
constexpr const static ::llvm::StringLiteral
2728
kDataLayoutAttrName = "dlti.dl_spec";
2829

30+
// Constants used in entries.
2931
constexpr const static ::llvm::StringLiteral
3032
kDataLayoutEndiannessKey = "dlti.endianness";
3133

@@ -34,6 +36,9 @@ def DLTI_Dialect : Dialect {
3436

3537
constexpr const static ::llvm::StringLiteral
3638
kDataLayoutEndiannessLittle = "little";
39+
40+
constexpr const static ::llvm::StringLiteral
41+
kDataLayoutAllocaMemorySpaceKey = "dlti.alloca_memory_space";
3742
}];
3843

3944
let useDefaultAttributePrinterParser = 1;

mlir/include/mlir/Interfaces/DataLayoutInterfaces.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ unsigned
5656
getDefaultPreferredAlignment(Type type, const DataLayout &dataLayout,
5757
ArrayRef<DataLayoutEntryInterface> params);
5858

59+
/// Default handler for alloca memory space request. Dispatches to the
60+
/// DataLayoutInterface if specified, otherwise returns the default.
61+
Attribute getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry);
62+
5963
/// Given a list of data layout entries, returns a new list containing the
6064
/// entries with keys having the given type ID, i.e. belonging to the same type
6165
/// class.
@@ -159,6 +163,9 @@ class DataLayout {
159163
/// Returns the preferred of the given type in the current scope.
160164
unsigned getTypePreferredAlignment(Type t) const;
161165

166+
/// Returns the memory space used for AllocaOps.
167+
Attribute getAllocaMemorySpace() const;
168+
162169
private:
163170
/// Combined layout spec at the given scope.
164171
const DataLayoutSpecInterface originalLayout;
@@ -180,6 +187,9 @@ class DataLayout {
180187
mutable DenseMap<Type, unsigned> bitsizes;
181188
mutable DenseMap<Type, unsigned> abiAlignments;
182189
mutable DenseMap<Type, unsigned> preferredAlignments;
190+
191+
/// Cache for alloca memory space.
192+
mutable std::optional<Attribute> allocaMemorySpace;
183193
};
184194

185195
} // namespace mlir

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 alloca memory space identifier.",
111+
/*retTy=*/"::mlir::StringAttr",
112+
/*methodName=*/"getAllocaMemorySpaceIdentifier",
113+
/*args=*/(ins "::mlir::MLIRContext *":$context)
114+
>,
109115
// Implementations may override this if they have an efficient lookup
110116
// mechanism.
111117
InterfaceMethod<
@@ -256,6 +262,18 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> {
256262
params);
257263
}]
258264
>,
265+
StaticInterfaceMethod<
266+
/*description=*/"Returns the memory space used by the ABI computed "
267+
"using the relevant entries. The data layout object "
268+
"can be used for recursive queries.",
269+
/*retTy=*/"::mlir::Attribute",
270+
/*methodName=*/"getAllocaMemorySpace",
271+
/*args=*/(ins "::mlir::DataLayoutEntryInterface":$entry),
272+
/*methodBody=*/"",
273+
/*defaultImplementation=*/[{
274+
return ::mlir::detail::getDefaultAllocaMemorySpace(entry);
275+
}]
276+
>,
259277
];
260278

261279
let verify = [{ return ::mlir::detail::verifyDataLayoutOp($_op); }];

mlir/lib/Dialect/DLTI/DLTI.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ void DataLayoutEntryAttr::print(AsmPrinter &os) const {
106106
//===----------------------------------------------------------------------===//
107107
//
108108
constexpr const StringLiteral mlir::DataLayoutSpecAttr::kAttrKeyword;
109+
constexpr const StringLiteral
110+
mlir::DLTIDialect::kDataLayoutAllocaMemorySpaceKey;
109111

110112
namespace mlir {
111113
namespace impl {
@@ -273,6 +275,12 @@ DataLayoutEntryListRef DataLayoutSpecAttr::getEntries() const {
273275
return getImpl()->entries;
274276
}
275277

278+
StringAttr
279+
DataLayoutSpecAttr::getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
280+
return Builder(context).getStringAttr(
281+
DLTIDialect::kDataLayoutAllocaMemorySpaceKey);
282+
}
283+
276284
/// Parses an attribute with syntax
277285
/// attr ::= `#target.` `dl_spec` `<` attr-list? `>`
278286
/// attr-list ::= attr
@@ -329,6 +337,8 @@ class TargetDataLayoutInterface : public DataLayoutDialectInterface {
329337
<< DLTIDialect::kDataLayoutEndiannessBig << "' or '"
330338
<< DLTIDialect::kDataLayoutEndiannessLittle << "'";
331339
}
340+
if (entryName == DLTIDialect::kDataLayoutAllocaMemorySpaceKey)
341+
return success();
332342
return emitError(loc) << "unknown data layout entry name: " << entryName;
333343
}
334344
};

mlir/lib/Interfaces/DataLayoutInterfaces.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,18 @@ unsigned mlir::detail::getDefaultPreferredAlignment(
213213
reportMissingDataLayout(type);
214214
}
215215

216+
// Returns the memory space used for allocal operations if specified in the
217+
// given entry. If the entry is empty the default memory space represented by
218+
// an empty attribute is returned.
219+
Attribute
220+
mlir::detail::getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry) {
221+
if (entry == DataLayoutEntryInterface()) {
222+
return Attribute();
223+
}
224+
225+
return entry.getValue();
226+
}
227+
216228
DataLayoutEntryList
217229
mlir::detail::filterEntriesForType(DataLayoutEntryListRef entries,
218230
TypeID typeID) {
@@ -346,15 +358,17 @@ void checkMissingLayout(DataLayoutSpecInterface originalLayout, OpTy op) {
346358
mlir::DataLayout::DataLayout() : DataLayout(ModuleOp()) {}
347359

348360
mlir::DataLayout::DataLayout(DataLayoutOpInterface op)
349-
: originalLayout(getCombinedDataLayout(op)), scope(op) {
361+
: originalLayout(getCombinedDataLayout(op)), scope(op),
362+
allocaMemorySpace(std::nullopt) {
350363
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
351364
checkMissingLayout(originalLayout, op);
352365
collectParentLayouts(op, layoutStack);
353366
#endif
354367
}
355368

356369
mlir::DataLayout::DataLayout(ModuleOp op)
357-
: originalLayout(getCombinedDataLayout(op)), scope(op) {
370+
: originalLayout(getCombinedDataLayout(op)), scope(op),
371+
allocaMemorySpace(std::nullopt) {
358372
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
359373
checkMissingLayout(originalLayout, op);
360374
collectParentLayouts(op, layoutStack);
@@ -456,6 +470,22 @@ unsigned mlir::DataLayout::getTypePreferredAlignment(Type t) const {
456470
});
457471
}
458472

473+
mlir::Attribute mlir::DataLayout::getAllocaMemorySpace() const {
474+
checkValid();
475+
MLIRContext *context = scope->getContext();
476+
if (allocaMemorySpace)
477+
return *allocaMemorySpace;
478+
DataLayoutEntryInterface entry;
479+
if (originalLayout)
480+
entry = originalLayout.getSpecForIdentifier(
481+
originalLayout.getAllocaMemorySpaceIdentifier(context));
482+
if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
483+
allocaMemorySpace = iface.getAllocaMemorySpace(entry);
484+
else
485+
allocaMemorySpace = detail::getDefaultAllocaMemorySpace(entry);
486+
return *allocaMemorySpace;
487+
}
488+
459489
//===----------------------------------------------------------------------===//
460490
// DataLayoutSpecInterface
461491
//===----------------------------------------------------------------------===//

mlir/lib/Target/LLVMIR/ModuleImport.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "mlir/Dialect/DLTI/DLTI.h"
2222
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
23+
#include "mlir/IR/Builders.h"
2324
#include "mlir/IR/Matchers.h"
2425
#include "mlir/Interfaces/DataLayoutInterfaces.h"
2526
#include "mlir/Tools/mlir-translate/Translation.h"
@@ -179,9 +180,10 @@ mlir::translateDataLayout(const llvm::DataLayout &dataLayout,
179180
// Remaining unhandled default layout defaults
180181
// e (little endian if not set)
181182
// p[n]:64:64:64 (non zero address spaces have 64-bit properties)
183+
// Alloca address space defaults to 0.
182184
std::string append =
183185
"p:64:64:64-S0-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f16:16:16-f64:"
184-
"64:64-f128:128:128-v64:64:64-v128:128:128-a:0:64";
186+
"64:64-f128:128:128-v64:64:64-v128:128:128-a:0:64-A0";
185187
if (layoutstr.empty())
186188
layoutstr = append;
187189
else
@@ -227,6 +229,18 @@ mlir::translateDataLayout(const llvm::DataLayout &dataLayout,
227229
StringAttr::get(context, DLTIDialect::kDataLayoutEndiannessKey),
228230
value);
229231
entries.emplace_back(entry);
232+
} else if (symbol == 'A') {
233+
unsigned addressSpace;
234+
if (parameter.getAsInteger(/*Radix=*/10, addressSpace))
235+
return nullptr;
236+
// Skip storing if generic address space is defined.
237+
if (addressSpace != 0) {
238+
auto entry = DataLayoutEntryAttr::get(
239+
StringAttr::get(context,
240+
DLTIDialect::kDataLayoutAllocaMemorySpaceKey),
241+
mlir::Builder(context).getUI32IntegerAttr(addressSpace));
242+
entries.emplace_back(entry);
243+
}
230244
}
231245
}
232246

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ translateDataLayout(DataLayoutSpecInterface attribute,
7979
layoutStream.flush();
8080
continue;
8181
}
82+
if (key.getValue() == DLTIDialect::kDataLayoutAllocaMemorySpaceKey) {
83+
auto value = entry.getValue().cast<IntegerAttr>();
84+
if (value != 0) {
85+
// Only emit non-default address space.
86+
layoutStream << "A" << value;
87+
layoutStream.flush();
88+
}
89+
continue;
90+
}
8291
emitError(*loc) << "unsupported data layout key " << key;
8392
return failure();
8493
}

mlir/test/Dialect/LLVMIR/layout.mlir

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,44 @@ module {
44
// CHECK: @no_spec
55
func.func @no_spec() {
66
// CHECK: alignment = 8
7+
// CHECK: alloca_memory_space = 0
78
// CHECK: bitsize = 64
89
// CHECK: preferred = 8
910
// CHECK: size = 8
1011
"test.data_layout_query"() : () -> !llvm.ptr<i8>
1112
// CHECK: alignment = 8
13+
// CHECK: alloca_memory_space = 0
1214
// CHECK: bitsize = 64
1315
// CHECK: preferred = 8
1416
// CHECK: size = 8
1517
"test.data_layout_query"() : () -> !llvm.ptr<i32>
1618
// CHECK: alignment = 8
19+
// CHECK: alloca_memory_space = 0
1720
// CHECK: bitsize = 64
1821
// CHECK: preferred = 8
1922
// CHECK: size = 8
2023
"test.data_layout_query"() : () -> !llvm.ptr<bf16>
2124
// CHECK: alignment = 8
25+
// CHECK: alloca_memory_space = 0
2226
// CHECK: bitsize = 64
2327
// CHECK: preferred = 8
2428
// CHECK: size = 8
2529
"test.data_layout_query"() : () -> !llvm.ptr<!llvm.ptr<i8>>
2630
// CHECK: alignment = 8
31+
// CHECK: alloca_memory_space = 0
2732
// CHECK: bitsize = 64
2833
// CHECK: preferred = 8
2934
// CHECK: size = 8
3035
"test.data_layout_query"() : () -> !llvm.ptr<i8, 3>
3136
// CHECK: alignment = 8
37+
// CHECK: alloca_memory_space = 0
3238
// CHECK: bitsize = 64
3339
// CHECK: preferred = 8
3440
// CHECK: size = 8
3541
"test.data_layout_query"() : () -> !llvm.ptr<i8, 5>
3642
// CHECK: alignment = 8
37-
// CHECK: bitsize = 64
43+
// CHECK: alloca_memory_space = 0
44+
// CHECK: bitsize = 64
3845
// CHECK: preferred = 8
3946
// CHECK: size = 8
4047
"test.data_layout_query"() : () -> !llvm.ptr<5>
@@ -47,47 +54,56 @@ module {
4754
module attributes { dlti.dl_spec = #dlti.dl_spec<
4855
#dlti.dl_entry<!llvm.ptr<i8>, dense<[32, 32, 64]> : vector<3xi32>>,
4956
#dlti.dl_entry<!llvm.ptr<i8, 5>, dense<[64, 64, 64]> : vector<3xi32>>,
50-
#dlti.dl_entry<!llvm.ptr<4>, dense<[32, 64, 64]> : vector<3xi32>>
57+
#dlti.dl_entry<!llvm.ptr<4>, dense<[32, 64, 64]> : vector<3xi32>>,
58+
#dlti.dl_entry<"dlti.alloca_memory_space", 5 : ui32>
5159
>} {
5260
// CHECK: @spec
5361
func.func @spec() {
5462
// CHECK: alignment = 4
63+
// CHECK: alloca_memory_space = 5
5564
// CHECK: bitsize = 32
5665
// CHECK: preferred = 8
5766
// CHECK: size = 4
5867
"test.data_layout_query"() : () -> !llvm.ptr<i8>
5968
// CHECK: alignment = 4
69+
// CHECK: alloca_memory_space = 5
6070
// CHECK: bitsize = 32
6171
// CHECK: preferred = 8
6272
// CHECK: size = 4
6373
"test.data_layout_query"() : () -> !llvm.ptr<i32>
6474
// CHECK: alignment = 4
75+
// CHECK: alloca_memory_space = 5
6576
// CHECK: bitsize = 32
6677
// CHECK: preferred = 8
6778
// CHECK: size = 4
6879
"test.data_layout_query"() : () -> !llvm.ptr<bf16>
6980
// CHECK: alignment = 4
81+
// CHECK: alloca_memory_space = 5
7082
// CHECK: bitsize = 32
7183
// CHECK: preferred = 8
7284
// CHECK: size = 4
7385
"test.data_layout_query"() : () -> !llvm.ptr<!llvm.ptr<i8>>
7486
// CHECK: alignment = 4
87+
// CHECK: alloca_memory_space = 5
7588
// CHECK: bitsize = 32
7689
// CHECK: preferred = 8
7790
// CHECK: size = 4
7891
"test.data_layout_query"() : () -> !llvm.ptr<i8, 3>
7992
// CHECK: alignment = 8
93+
// CHECK: alloca_memory_space = 5
8094
// CHECK: bitsize = 64
8195
// CHECK: preferred = 8
8296
// CHECK: size = 8
8397
"test.data_layout_query"() : () -> !llvm.ptr<i8, 5>
8498
// CHECK: alignment = 4
85-
// CHECK: bitsize = 32
99+
// CHECK: alloca_memory_space = 5
100+
// CHECK: bitsize = 32
86101
// CHECK: preferred = 8
87102
// CHECK: size = 4
88103
"test.data_layout_query"() : () -> !llvm.ptr<3>
89104
// CHECK: alignment = 8
90-
// CHECK: bitsize = 32
105+
// CHECK: alloca_memory_space = 5
106+
// CHECK: bitsize = 32
91107
// CHECK: preferred = 8
92108
// CHECK: size = 4
93109
"test.data_layout_query"() : () -> !llvm.ptr<4>

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,18 @@ struct TestDataLayoutQuery
4040
unsigned bitsize = layout.getTypeSizeInBits(op.getType());
4141
unsigned alignment = layout.getTypeABIAlignment(op.getType());
4242
unsigned preferred = layout.getTypePreferredAlignment(op.getType());
43+
Attribute allocaMemorySpace = layout.getAllocaMemorySpace();
4344
op->setAttrs(
4445
{builder.getNamedAttr("size", builder.getIndexAttr(size)),
4546
builder.getNamedAttr("bitsize", builder.getIndexAttr(bitsize)),
4647
builder.getNamedAttr("alignment", builder.getIndexAttr(alignment)),
47-
builder.getNamedAttr("preferred", builder.getIndexAttr(preferred))});
48+
builder.getNamedAttr("preferred", builder.getIndexAttr(preferred)),
49+
builder.getNamedAttr("alloca_memory_space",
50+
allocaMemorySpace == Attribute()
51+
? builder.getUI32IntegerAttr(0)
52+
: allocaMemorySpace)
53+
54+
});
4855
});
4956
}
5057
};

0 commit comments

Comments
 (0)