Skip to content

Commit aa00e3e

Browse files
committed
[mlir][llvm] Support pointer entries in data layout translation
This adds support for pointer DLTI entries in LLVMIR export, e.g. ``` // translated to: p0:32:64:128 #dlti.dl_entry<!llvm.ptr, dense<[32,64,128]> : vector<3xi32>> // translated to: p1:32:32:32:64 #dlti.dl_entry<!llvm.ptr<1>, dense<[32,32,32,64]> : vector<4xi32>> ``` Reviewed By: ftynse Differential Revision: https://reviews.llvm.org/D133434
1 parent bc14ed7 commit aa00e3e

File tree

4 files changed

+78
-53
lines changed

4 files changed

+78
-53
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,15 @@ Type getScalableVectorType(Type elementType, unsigned numElements);
535535
/// (aggregates such as struct) or types that don't have a size (such as void).
536536
llvm::TypeSize getPrimitiveTypeSizeInBits(Type type);
537537

538+
/// The positions of different values in the data layout entry for pointers.
539+
enum class PtrDLEntryPos { Size = 0, Abi = 1, Preferred = 2, Index = 3 };
540+
541+
/// Returns the value that corresponds to named position `pos` from the
542+
/// data layout entry `attr` assuming it's a dense integer elements attribute.
543+
/// Returns `None` if `pos` is not present in the entry.
544+
/// Currently only `PtrDLEntryPos::Index` is optional, and all other positions
545+
/// may be assumed to be present.
546+
Optional<unsigned> extractPointerSpecValue(Attribute attr, PtrDLEntryPos pos);
538547
} // namespace LLVM
539548
} // namespace mlir
540549

mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -229,19 +229,16 @@ LLVMPointerType::verify(function_ref<InFlightDiagnostic()> emitError,
229229
return success();
230230
}
231231

232-
namespace {
233-
/// The positions of different values in the data layout entry.
234-
enum class DLEntryPos { Size = 0, Abi = 1, Preferred = 2, Address = 3 };
235-
} // namespace
236-
237232
constexpr const static unsigned kDefaultPointerSizeBits = 64;
238233
constexpr const static unsigned kDefaultPointerAlignment = 8;
239234

240-
/// Returns the value that corresponds to named position `pos` from the
241-
/// attribute `attr` assuming it's a dense integer elements attribute.
242-
static unsigned extractPointerSpecValue(Attribute attr, DLEntryPos pos) {
243-
return attr.cast<DenseIntElementsAttr>()
244-
.getValues<unsigned>()[static_cast<unsigned>(pos)];
235+
Optional<unsigned> mlir::LLVM::extractPointerSpecValue(Attribute attr,
236+
PtrDLEntryPos pos) {
237+
auto spec = attr.cast<DenseIntElementsAttr>();
238+
auto idx = static_cast<unsigned>(pos);
239+
if (idx >= spec.size())
240+
return None;
241+
return spec.getValues<unsigned>()[idx];
245242
}
246243

247244
/// Returns the part of the data layout entry that corresponds to `pos` for the
@@ -250,7 +247,7 @@ static unsigned extractPointerSpecValue(Attribute attr, DLEntryPos pos) {
250247
/// do not provide a custom one, for other address spaces returns None.
251248
static Optional<unsigned>
252249
getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type,
253-
DLEntryPos pos) {
250+
PtrDLEntryPos pos) {
254251
// First, look for the entry for the pointer in the current address space.
255252
Attribute currentEntry;
256253
for (DataLayoutEntryInterface entry : params) {
@@ -263,15 +260,15 @@ getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type,
263260
}
264261
}
265262
if (currentEntry) {
266-
return extractPointerSpecValue(currentEntry, pos) /
267-
(pos == DLEntryPos::Size ? 1 : kBitsInByte);
263+
return *extractPointerSpecValue(currentEntry, pos) /
264+
(pos == PtrDLEntryPos::Size ? 1 : kBitsInByte);
268265
}
269266

270267
// If not found, and this is the pointer to the default memory space, assume
271268
// 64-bit pointers.
272269
if (type.getAddressSpace() == 0) {
273-
return pos == DLEntryPos::Size ? kDefaultPointerSizeBits
274-
: kDefaultPointerAlignment;
270+
return pos == PtrDLEntryPos::Size ? kDefaultPointerSizeBits
271+
: kDefaultPointerAlignment;
275272
}
276273

277274
return llvm::None;
@@ -281,7 +278,7 @@ unsigned
281278
LLVMPointerType::getTypeSizeInBits(const DataLayout &dataLayout,
282279
DataLayoutEntryListRef params) const {
283280
if (Optional<unsigned> size =
284-
getPointerDataLayoutEntry(params, *this, DLEntryPos::Size))
281+
getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Size))
285282
return *size;
286283

287284
// For other memory spaces, use the size of the pointer to the default memory
@@ -294,7 +291,7 @@ LLVMPointerType::getTypeSizeInBits(const DataLayout &dataLayout,
294291
unsigned LLVMPointerType::getABIAlignment(const DataLayout &dataLayout,
295292
DataLayoutEntryListRef params) const {
296293
if (Optional<unsigned> alignment =
297-
getPointerDataLayoutEntry(params, *this, DLEntryPos::Abi))
294+
getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Abi))
298295
return *alignment;
299296

300297
if (isOpaque())
@@ -306,7 +303,7 @@ unsigned
306303
LLVMPointerType::getPreferredAlignment(const DataLayout &dataLayout,
307304
DataLayoutEntryListRef params) const {
308305
if (Optional<unsigned> alignment =
309-
getPointerDataLayoutEntry(params, *this, DLEntryPos::Preferred))
306+
getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Preferred))
310307
return *alignment;
311308

312309
if (isOpaque())
@@ -339,13 +336,13 @@ bool LLVMPointerType::areCompatible(DataLayoutEntryListRef oldLayout,
339336
});
340337
}
341338
if (it != oldLayout.end()) {
342-
size = extractPointerSpecValue(*it, DLEntryPos::Size);
343-
abi = extractPointerSpecValue(*it, DLEntryPos::Abi);
339+
size = *extractPointerSpecValue(*it, PtrDLEntryPos::Size);
340+
abi = *extractPointerSpecValue(*it, PtrDLEntryPos::Abi);
344341
}
345342

346343
Attribute newSpec = newEntry.getValue().cast<DenseIntElementsAttr>();
347-
unsigned newSize = extractPointerSpecValue(newSpec, DLEntryPos::Size);
348-
unsigned newAbi = extractPointerSpecValue(newSpec, DLEntryPos::Abi);
344+
unsigned newSize = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Size);
345+
unsigned newAbi = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Abi);
349346
if (size != newSize || abi < newAbi || abi % newAbi != 0)
350347
return false;
351348
}
@@ -369,8 +366,8 @@ LogicalResult LLVMPointerType::verifyEntries(DataLayoutEntryListRef entries,
369366
return emitError(loc) << "unexpected layout attribute for pointer to "
370367
<< key.getElementType();
371368
}
372-
if (extractPointerSpecValue(values, DLEntryPos::Abi) >
373-
extractPointerSpecValue(values, DLEntryPos::Preferred)) {
369+
if (extractPointerSpecValue(values, PtrDLEntryPos::Abi) >
370+
extractPointerSpecValue(values, PtrDLEntryPos::Preferred)) {
374371
return emitError(loc) << "preferred alignment is expected to be at least "
375372
"as large as ABI alignment";
376373
}

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ using namespace mlir::LLVM::detail;
5252
#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
5353

5454
/// Translates the given data layout spec attribute to the LLVM IR data layout.
55-
/// Only integer, float and endianness entries are currently supported.
56-
FailureOr<llvm::DataLayout>
55+
/// Only integer, float, pointer and endianness entries are currently supported.
56+
static FailureOr<llvm::DataLayout>
5757
translateDataLayout(DataLayoutSpecInterface attribute,
5858
const DataLayout &dataLayout,
5959
Optional<Location> loc = llvm::None) {
@@ -80,41 +80,56 @@ translateDataLayout(DataLayoutSpecInterface attribute,
8080
}
8181

8282
// Go through the list of entries to check which types are explicitly
83-
// specified in entries. Don't use the entries directly though but query the
84-
// data from the layout.
83+
// specified in entries. Where possible, data layout queries are used instead
84+
// of directly inspecting the entries.
8585
for (DataLayoutEntryInterface entry : attribute.getEntries()) {
8686
auto type = entry.getKey().dyn_cast<Type>();
8787
if (!type)
8888
continue;
8989
// Data layout for the index type is irrelevant at this point.
9090
if (type.isa<IndexType>())
9191
continue;
92-
FailureOr<std::string> prefix =
93-
llvm::TypeSwitch<Type, FailureOr<std::string>>(type)
94-
.Case<IntegerType>(
95-
[loc](IntegerType integerType) -> FailureOr<std::string> {
96-
if (integerType.getSignedness() == IntegerType::Signless)
97-
return std::string("i");
98-
emitError(*loc)
99-
<< "unsupported data layout for non-signless integer "
100-
<< integerType;
101-
return failure();
102-
})
103-
.Case<Float16Type, Float32Type, Float64Type, Float80Type,
104-
Float128Type>([](Type) { return std::string("f"); })
105-
.Default([loc](Type type) -> FailureOr<std::string> {
106-
emitError(*loc) << "unsupported type in data layout: " << type;
107-
return failure();
92+
layoutStream << "-";
93+
LogicalResult result =
94+
llvm::TypeSwitch<Type, LogicalResult>(type)
95+
.Case<IntegerType, Float16Type, Float32Type, Float64Type,
96+
Float80Type, Float128Type>([&](Type type) -> LogicalResult {
97+
if (auto intType = type.dyn_cast<IntegerType>()) {
98+
if (intType.getSignedness() != IntegerType::Signless)
99+
return emitError(*loc)
100+
<< "unsupported data layout for non-signless integer "
101+
<< intType;
102+
layoutStream << "i";
103+
} else {
104+
layoutStream << "f";
105+
}
106+
unsigned size = dataLayout.getTypeSizeInBits(type);
107+
unsigned abi = dataLayout.getTypeABIAlignment(type) * 8u;
108+
unsigned preferred =
109+
dataLayout.getTypePreferredAlignment(type) * 8u;
110+
layoutStream << size << ":" << abi;
111+
if (abi != preferred)
112+
layoutStream << ":" << preferred;
113+
return success();
114+
})
115+
.Case([&](LLVMPointerType ptrType) {
116+
layoutStream << "p" << ptrType.getAddressSpace() << ":";
117+
unsigned size = dataLayout.getTypeSizeInBits(type);
118+
unsigned abi = dataLayout.getTypeABIAlignment(type) * 8u;
119+
unsigned preferred =
120+
dataLayout.getTypePreferredAlignment(type) * 8u;
121+
layoutStream << size << ":" << abi << ":" << preferred;
122+
if (Optional<unsigned> index = extractPointerSpecValue(
123+
entry.getValue(), PtrDLEntryPos::Index))
124+
layoutStream << ":" << *index;
125+
return success();
126+
})
127+
.Default([loc](Type type) {
128+
return emitError(*loc)
129+
<< "unsupported type in data layout: " << type;
108130
});
109-
if (failed(prefix))
131+
if (failed(result))
110132
return failure();
111-
112-
unsigned size = dataLayout.getTypeSizeInBits(type);
113-
unsigned abi = dataLayout.getTypeABIAlignment(type) * 8u;
114-
unsigned preferred = dataLayout.getTypePreferredAlignment(type) * 8u;
115-
layoutStream << "-" << *prefix << size << ":" << abi;
116-
if (abi != preferred)
117-
layoutStream << ":" << preferred;
118133
}
119134
layoutStream.flush();
120135
StringRef layoutSpec(llvmDataLayout);

mlir/test/Target/LLVMIR/data-layout.mlir

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
// CHECK: E-
55
// CHECK: i64:64:128
66
// CHECK: f80:128:256
7+
// CHECK: p0:32:64:128
8+
// CHECK: p1:32:32:32:64
79
module attributes {dlti.dl_spec = #dlti.dl_spec<
810
#dlti.dl_entry<"dlti.endianness", "big">,
911
#dlti.dl_entry<index, 64>,
1012
#dlti.dl_entry<i64, dense<[64,128]> : vector<2xi32>>,
11-
#dlti.dl_entry<f80, dense<[128,256]> : vector<2xi32>>
13+
#dlti.dl_entry<f80, dense<[128,256]> : vector<2xi32>>,
14+
#dlti.dl_entry<!llvm.ptr, dense<[32,64,128]> : vector<3xi32>>,
15+
#dlti.dl_entry<!llvm.ptr<1>, dense<[32,32,32,64]> : vector<4xi32>>
1216
>} {
1317
llvm.func @foo() {
1418
llvm.return

0 commit comments

Comments
 (0)