Skip to content

Commit f64170a

Browse files
committed
[mlir] Data layout for integer and float types
Add support for integer and float types into the data layout subsystem with default logic similar to LLVM IR. Given the flexibility of the sybsystem, the logic can be easily overwritten by operations if necessary. This provides the connection necessary, e.g., for the GPU target where alignment requirements for integers and floats differ from those provided by default (although still compatible with the LLVM IR model). Previously, it was impossible to use non-default alignment requirements for integer and float types, which could lead to incorrect address and size calculations when targeting GPUs. Depends On D120737 Reviewed By: wsmoses Differential Revision: https://reviews.llvm.org/D120739
1 parent 554839e commit f64170a

File tree

4 files changed

+223
-12
lines changed

4 files changed

+223
-12
lines changed

mlir/lib/Interfaces/DataLayoutInterfaces.cpp

Lines changed: 119 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,23 +86,67 @@ unsigned mlir::detail::getDefaultTypeSizeInBits(Type type,
8686
reportMissingDataLayout(type);
8787
}
8888

89+
static DataLayoutEntryInterface
90+
findEntryForIntegerType(IntegerType intType,
91+
ArrayRef<DataLayoutEntryInterface> params) {
92+
assert(!params.empty() && "expected non-empty parameter list");
93+
std::map<unsigned, DataLayoutEntryInterface> sortedParams;
94+
for (DataLayoutEntryInterface entry : params) {
95+
sortedParams.insert(std::make_pair(
96+
entry.getKey().get<Type>().getIntOrFloatBitWidth(), entry));
97+
}
98+
auto iter = sortedParams.lower_bound(intType.getWidth());
99+
if (iter == sortedParams.end())
100+
iter = std::prev(iter);
101+
102+
return iter->second;
103+
}
104+
105+
static unsigned extractABIAlignment(DataLayoutEntryInterface entry) {
106+
auto values =
107+
entry.getValue().cast<DenseIntElementsAttr>().getValues<int32_t>();
108+
return *values.begin() / 8u;
109+
}
110+
111+
static unsigned
112+
getIntegerTypeABIAlignment(IntegerType intType,
113+
ArrayRef<DataLayoutEntryInterface> params) {
114+
if (params.empty()) {
115+
return intType.getWidth() < 64
116+
? llvm::PowerOf2Ceil(llvm::divideCeil(intType.getWidth(), 8))
117+
: 4;
118+
}
119+
120+
return extractABIAlignment(findEntryForIntegerType(intType, params));
121+
}
122+
123+
static unsigned
124+
getFloatTypeABIAlignment(FloatType fltType, const DataLayout &dataLayout,
125+
ArrayRef<DataLayoutEntryInterface> params) {
126+
assert(params.size() <= 1 && "at most one data layout entry is expected for "
127+
"the singleton floating-point type");
128+
if (params.empty())
129+
return llvm::PowerOf2Ceil(dataLayout.getTypeSize(fltType));
130+
return extractABIAlignment(params[0]);
131+
}
132+
89133
unsigned mlir::detail::getDefaultABIAlignment(
90134
Type type, const DataLayout &dataLayout,
91135
ArrayRef<DataLayoutEntryInterface> params) {
92136
// Natural alignment is the closest power-of-two number above.
93-
if (type.isa<FloatType, VectorType>())
137+
if (type.isa<VectorType>())
94138
return llvm::PowerOf2Ceil(dataLayout.getTypeSize(type));
95139

140+
if (auto fltType = type.dyn_cast<FloatType>())
141+
return getFloatTypeABIAlignment(fltType, dataLayout, params);
142+
96143
// Index is an integer of some bitwidth.
97144
if (type.isa<IndexType>())
98145
return dataLayout.getTypeABIAlignment(
99146
IntegerType::get(type.getContext(), getIndexBitwidth(params)));
100147

101-
if (auto intType = type.dyn_cast<IntegerType>()) {
102-
return intType.getWidth() < 64
103-
? llvm::PowerOf2Ceil(llvm::divideCeil(intType.getWidth(), 8))
104-
: 4;
105-
}
148+
if (auto intType = type.dyn_cast<IntegerType>())
149+
return getIntegerTypeABIAlignment(intType, params);
106150

107151
if (auto ctype = type.dyn_cast<ComplexType>())
108152
return getDefaultABIAlignment(ctype.getElementType(), dataLayout, params);
@@ -113,17 +157,51 @@ unsigned mlir::detail::getDefaultABIAlignment(
113157
reportMissingDataLayout(type);
114158
}
115159

160+
static unsigned extractPreferredAlignment(DataLayoutEntryInterface entry) {
161+
auto values =
162+
entry.getValue().cast<DenseIntElementsAttr>().getValues<int32_t>();
163+
return *std::next(values.begin(), values.size() - 1) / 8u;
164+
}
165+
166+
static unsigned
167+
getIntegerTypePreferredAlignment(IntegerType intType,
168+
const DataLayout &dataLayout,
169+
ArrayRef<DataLayoutEntryInterface> params) {
170+
if (params.empty())
171+
return llvm::PowerOf2Ceil(dataLayout.getTypeSize(intType));
172+
173+
return extractPreferredAlignment(findEntryForIntegerType(intType, params));
174+
}
175+
176+
static unsigned
177+
getFloatTypePreferredAlignment(FloatType fltType, const DataLayout &dataLayout,
178+
ArrayRef<DataLayoutEntryInterface> params) {
179+
assert(params.size() <= 1 && "at most one data layout entry is expected for "
180+
"the singleton floating-point type");
181+
if (params.empty())
182+
return dataLayout.getTypeABIAlignment(fltType);
183+
return extractPreferredAlignment(params[0]);
184+
}
185+
116186
unsigned mlir::detail::getDefaultPreferredAlignment(
117187
Type type, const DataLayout &dataLayout,
118188
ArrayRef<DataLayoutEntryInterface> params) {
119189
// Preferred alignment is same as natural for floats and vectors.
120-
if (type.isa<FloatType, VectorType>())
190+
if (type.isa<VectorType>())
121191
return dataLayout.getTypeABIAlignment(type);
122192

123-
// Preferred alignment is the cloest power-of-two number above for integers
193+
if (auto fltType = type.dyn_cast<FloatType>())
194+
return getFloatTypePreferredAlignment(fltType, dataLayout, params);
195+
196+
// Preferred alignment is the closest power-of-two number above for integers
124197
// (ABI alignment may be smaller).
125-
if (type.isa<IntegerType, IndexType>())
126-
return llvm::PowerOf2Ceil(dataLayout.getTypeSize(type));
198+
if (auto intType = type.dyn_cast<IntegerType>())
199+
return getIntegerTypePreferredAlignment(intType, dataLayout, params);
200+
201+
if (type.isa<IndexType>()) {
202+
return dataLayout.getTypePreferredAlignment(
203+
IntegerType::get(type.getContext(), getIndexBitwidth(params)));
204+
}
127205

128206
if (auto ctype = type.dyn_cast<ComplexType>())
129207
return getDefaultPreferredAlignment(ctype.getElementType(), dataLayout,
@@ -418,6 +496,37 @@ LogicalResult mlir::detail::verifyDataLayoutSpec(DataLayoutSpecInterface spec,
418496
continue;
419497
}
420498

499+
if (sampleType.isa<IntegerType, FloatType>()) {
500+
for (DataLayoutEntryInterface entry : kvp.second) {
501+
auto value = entry.getValue().dyn_cast<DenseIntElementsAttr>();
502+
if (!value || !value.getElementType().isSignlessInteger(32)) {
503+
emitError(loc) << "expected a dense i32 elements attribute in the "
504+
"data layout entry "
505+
<< entry;
506+
return failure();
507+
}
508+
509+
auto elements = llvm::to_vector<2>(value.getValues<int32_t>());
510+
unsigned numElements = elements.size();
511+
if (numElements < 1 || numElements > 2) {
512+
emitError(loc) << "expected 1 or 2 elements in the data layout entry "
513+
<< entry;
514+
return failure();
515+
}
516+
517+
int32_t abi = elements[0];
518+
int32_t preferred = numElements == 2 ? elements[1] : abi;
519+
if (preferred < abi) {
520+
emitError(loc)
521+
<< "preferred alignment is expected to be greater than or equal "
522+
"to the abi alignment in data layout entry "
523+
<< entry;
524+
return failure();
525+
}
526+
}
527+
continue;
528+
}
529+
421530
if (isa<BuiltinDialect>(&sampleType.getDialect()))
422531
return emitError(loc) << "unexpected data layout for a built-in type";
423532

mlir/test/Dialect/DLTI/invalid.mlir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@
6363

6464
// -----
6565

66-
// Layout not supported for built-in types.
66+
// Layout not supported some built-in types.
6767
// expected-error@below {{unexpected data layout for a built-in type}}
68-
"test.op_with_data_layout"() { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<i32, 32>> } : () -> ()
68+
"test.op_with_data_layout"() { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<tensor<f32>, 32>> } : () -> ()
6969

7070
// -----
7171

mlir/test/Interfaces/DataLayoutInterfaces/query.mlir

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,84 @@ func @nested_combine_all() {
194194
>}: () -> ()
195195
return
196196
}
197+
198+
// CHECK-LABEL: @integers
199+
func @integers() {
200+
"test.op_with_data_layout"() ({
201+
// CHECK: alignment = 8
202+
// CHECK: bitsize = 32
203+
// CHECK: preferred = 8
204+
"test.data_layout_query"() : () -> i32
205+
// CHECK: alignment = 16
206+
// CHECK: bitsize = 56
207+
// CHECK: preferred = 16
208+
"test.data_layout_query"() : () -> i56
209+
// CHECK: alignment = 16
210+
// CHECK: bitsize = 64
211+
// CHECK: preferred = 16
212+
"test.data_layout_query"() : () -> i64
213+
// CHECK: alignment = 16
214+
// CHECK: bitsize = 128
215+
// CHECK: preferred = 16
216+
"test.data_layout_query"() : () -> i128
217+
"test.maybe_terminator"() : () -> ()
218+
}) { dlti.dl_spec = #dlti.dl_spec<
219+
#dlti.dl_entry<i32, dense<64> : vector<1xi32>>,
220+
#dlti.dl_entry<i64, dense<128> : vector<1xi32>>
221+
>} : () -> ()
222+
"test.op_with_data_layout"() ({
223+
// CHECK: alignment = 8
224+
// CHECK: bitsize = 32
225+
// CHECK: preferred = 16
226+
"test.data_layout_query"() : () -> i32
227+
// CHECK: alignment = 16
228+
// CHECK: bitsize = 56
229+
// CHECK: preferred = 32
230+
"test.data_layout_query"() : () -> i56
231+
// CHECK: alignment = 16
232+
// CHECK: bitsize = 64
233+
// CHECK: preferred = 32
234+
"test.data_layout_query"() : () -> i64
235+
// CHECK: alignment = 16
236+
// CHECK: bitsize = 128
237+
// CHECK: preferred = 32
238+
"test.data_layout_query"() : () -> i128
239+
"test.maybe_terminator"() : () -> ()
240+
}) { dlti.dl_spec = #dlti.dl_spec<
241+
#dlti.dl_entry<i32, dense<[64, 128]> : vector<2xi32>>,
242+
#dlti.dl_entry<i64, dense<[128, 256]> : vector<2xi32>>
243+
>} : () -> ()
244+
return
245+
}
246+
247+
func @floats() {
248+
"test.op_with_data_layout"() ({
249+
// CHECK: alignment = 8
250+
// CHECK: bitsize = 32
251+
// CHECK: preferred = 8
252+
"test.data_layout_query"() : () -> f32
253+
// CHECK: alignment = 16
254+
// CHECK: bitsize = 80
255+
// CHECK: preferred = 16
256+
"test.data_layout_query"() : () -> f80
257+
"test.maybe_terminator"() : () -> ()
258+
}) { dlti.dl_spec = #dlti.dl_spec<
259+
#dlti.dl_entry<f32, dense<64> : vector<1xi32>>,
260+
#dlti.dl_entry<f80, dense<128> : vector<1xi32>>
261+
>} : () -> ()
262+
"test.op_with_data_layout"() ({
263+
// CHECK: alignment = 8
264+
// CHECK: bitsize = 32
265+
// CHECK: preferred = 16
266+
"test.data_layout_query"() : () -> f32
267+
// CHECK: alignment = 16
268+
// CHECK: bitsize = 80
269+
// CHECK: preferred = 32
270+
"test.data_layout_query"() : () -> f80
271+
"test.maybe_terminator"() : () -> ()
272+
}) { dlti.dl_spec = #dlti.dl_spec<
273+
#dlti.dl_entry<f32, dense<[64, 128]> : vector<2xi32>>,
274+
#dlti.dl_entry<f80, dense<[128, 256]> : vector<2xi32>>
275+
>} : () -> ()
276+
return
277+
}

mlir/test/Interfaces/DataLayoutInterfaces/types.mlir

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,27 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
77

88
// -----
99

10+
// expected-error@below {{expected a dense i32 elements attribute}}
11+
module attributes {dlti.dl_spec = #dlti.dl_spec<
12+
#dlti.dl_entry<i32, dense<[64,128]> : vector<2xi64>>>
13+
} {}
14+
15+
// -----
16+
17+
// expected-error@below {{expected 1 or 2 elements}}
18+
module attributes {dlti.dl_spec = #dlti.dl_spec<
19+
#dlti.dl_entry<i32, dense<[64,64,64]> : vector<3xi32>>>
20+
} {}
21+
22+
// -----
23+
24+
// expected-error@below {{preferred alignment is expected to be greater than or equal to the abi alignment}}
25+
module attributes {dlti.dl_spec = #dlti.dl_spec<
26+
#dlti.dl_entry<i32, dense<[64,32]> : vector<2xi32>>>
27+
} {}
28+
29+
// -----
30+
1031
// expected-error@below {{the 'test' dialect does not support identifier data layout entries}}
1132
"test.op_with_data_layout"() { dlti.dl_spec = #dlti.dl_spec<
1233
#dlti.dl_entry<index, 32>,

0 commit comments

Comments
 (0)