diff --git a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp --- a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp +++ b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp @@ -86,23 +86,67 @@ reportMissingDataLayout(type); } +static DataLayoutEntryInterface +findEntryForIntegerType(IntegerType intType, + ArrayRef params) { + assert(!params.empty() && "expected non-empty parameter list"); + std::map sortedParams; + for (DataLayoutEntryInterface entry : params) { + sortedParams.insert(std::make_pair( + entry.getKey().get().getIntOrFloatBitWidth(), entry)); + } + auto iter = sortedParams.lower_bound(intType.getWidth()); + if (iter == sortedParams.end()) + iter = std::prev(iter); + + return iter->second; +} + +static unsigned extractABIAlignment(DataLayoutEntryInterface entry) { + auto values = + entry.getValue().cast().getValues(); + return *values.begin() / 8u; +} + +static unsigned +getIntegerTypeABIAlignment(IntegerType intType, + ArrayRef params) { + if (params.empty()) { + return intType.getWidth() < 64 + ? llvm::PowerOf2Ceil(llvm::divideCeil(intType.getWidth(), 8)) + : 4; + } + + return extractABIAlignment(findEntryForIntegerType(intType, params)); +} + +static unsigned +getFloatTypeABIAlignment(FloatType fltType, const DataLayout &dataLayout, + ArrayRef params) { + assert(params.size() <= 1 && "at most one data layout entry is expected for " + "the singleton floating-point type"); + if (params.empty()) + return llvm::PowerOf2Ceil(dataLayout.getTypeSize(fltType)); + return extractABIAlignment(params[0]); +} + unsigned mlir::detail::getDefaultABIAlignment( Type type, const DataLayout &dataLayout, ArrayRef params) { // Natural alignment is the closest power-of-two number above. - if (type.isa()) + if (type.isa()) return llvm::PowerOf2Ceil(dataLayout.getTypeSize(type)); + if (auto fltType = type.dyn_cast()) + return getFloatTypeABIAlignment(fltType, dataLayout, params); + // Index is an integer of some bitwidth. if (type.isa()) return dataLayout.getTypeABIAlignment( IntegerType::get(type.getContext(), getIndexBitwidth(params))); - if (auto intType = type.dyn_cast()) { - return intType.getWidth() < 64 - ? llvm::PowerOf2Ceil(llvm::divideCeil(intType.getWidth(), 8)) - : 4; - } + if (auto intType = type.dyn_cast()) + return getIntegerTypeABIAlignment(intType, params); if (auto ctype = type.dyn_cast()) return getDefaultABIAlignment(ctype.getElementType(), dataLayout, params); @@ -113,17 +157,51 @@ reportMissingDataLayout(type); } +static unsigned extractPreferredAlignment(DataLayoutEntryInterface entry) { + auto values = + entry.getValue().cast().getValues(); + return *std::next(values.begin(), values.size() - 1) / 8u; +} + +static unsigned +getIntegerTypePreferredAlignment(IntegerType intType, + const DataLayout &dataLayout, + ArrayRef params) { + if (params.empty()) + return llvm::PowerOf2Ceil(dataLayout.getTypeSize(intType)); + + return extractPreferredAlignment(findEntryForIntegerType(intType, params)); +} + +static unsigned +getFloatTypePreferredAlignment(FloatType fltType, const DataLayout &dataLayout, + ArrayRef params) { + assert(params.size() <= 1 && "at most one data layout entry is expected for " + "the singleton floating-point type"); + if (params.empty()) + return dataLayout.getTypeABIAlignment(fltType); + return extractPreferredAlignment(params[0]); +} + unsigned mlir::detail::getDefaultPreferredAlignment( Type type, const DataLayout &dataLayout, ArrayRef params) { // Preferred alignment is same as natural for floats and vectors. - if (type.isa()) + if (type.isa()) return dataLayout.getTypeABIAlignment(type); - // Preferred alignment is the cloest power-of-two number above for integers + if (auto fltType = type.dyn_cast()) + return getFloatTypePreferredAlignment(fltType, dataLayout, params); + + // Preferred alignment is the closest power-of-two number above for integers // (ABI alignment may be smaller). - if (type.isa()) - return llvm::PowerOf2Ceil(dataLayout.getTypeSize(type)); + if (auto intType = type.dyn_cast()) + return getIntegerTypePreferredAlignment(intType, dataLayout, params); + + if (type.isa()) { + return dataLayout.getTypePreferredAlignment( + IntegerType::get(type.getContext(), getIndexBitwidth(params))); + } if (auto ctype = type.dyn_cast()) return getDefaultPreferredAlignment(ctype.getElementType(), dataLayout, @@ -418,6 +496,37 @@ continue; } + if (sampleType.isa()) { + for (DataLayoutEntryInterface entry : kvp.second) { + auto value = entry.getValue().dyn_cast(); + if (!value || !value.getElementType().isSignlessInteger(32)) { + emitError(loc) << "expected a dense i32 elements attribute in the " + "data layout entry " + << entry; + return failure(); + } + + auto elements = llvm::to_vector<2>(value.getValues()); + unsigned numElements = elements.size(); + if (numElements < 1 || numElements > 2) { + emitError(loc) << "expected 1 or 2 elements in the data layout entry " + << entry; + return failure(); + } + + int32_t abi = elements[0]; + int32_t preferred = numElements == 2 ? elements[1] : abi; + if (preferred < abi) { + emitError(loc) + << "preferred alignment is expected to be greater than or equal " + "to the abi alignment in data layout entry " + << entry; + return failure(); + } + } + continue; + } + if (isa(&sampleType.getDialect())) return emitError(loc) << "unexpected data layout for a built-in type"; diff --git a/mlir/test/Dialect/DLTI/invalid.mlir b/mlir/test/Dialect/DLTI/invalid.mlir --- a/mlir/test/Dialect/DLTI/invalid.mlir +++ b/mlir/test/Dialect/DLTI/invalid.mlir @@ -63,9 +63,9 @@ // ----- -// Layout not supported for built-in types. +// Layout not supported some built-in types. // expected-error@below {{unexpected data layout for a built-in type}} -"test.op_with_data_layout"() { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry> } : () -> () +"test.op_with_data_layout"() { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry, 32>> } : () -> () // ----- diff --git a/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir b/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir --- a/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir +++ b/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir @@ -194,3 +194,84 @@ >}: () -> () return } + +// CHECK-LABEL: @integers +func @integers() { + "test.op_with_data_layout"() ({ + // CHECK: alignment = 8 + // CHECK: bitsize = 32 + // CHECK: preferred = 8 + "test.data_layout_query"() : () -> i32 + // CHECK: alignment = 16 + // CHECK: bitsize = 56 + // CHECK: preferred = 16 + "test.data_layout_query"() : () -> i56 + // CHECK: alignment = 16 + // CHECK: bitsize = 64 + // CHECK: preferred = 16 + "test.data_layout_query"() : () -> i64 + // CHECK: alignment = 16 + // CHECK: bitsize = 128 + // CHECK: preferred = 16 + "test.data_layout_query"() : () -> i128 + "test.maybe_terminator"() : () -> () + }) { dlti.dl_spec = #dlti.dl_spec< + #dlti.dl_entry : vector<1xi32>>, + #dlti.dl_entry : vector<1xi32>> + >} : () -> () + "test.op_with_data_layout"() ({ + // CHECK: alignment = 8 + // CHECK: bitsize = 32 + // CHECK: preferred = 16 + "test.data_layout_query"() : () -> i32 + // CHECK: alignment = 16 + // CHECK: bitsize = 56 + // CHECK: preferred = 32 + "test.data_layout_query"() : () -> i56 + // CHECK: alignment = 16 + // CHECK: bitsize = 64 + // CHECK: preferred = 32 + "test.data_layout_query"() : () -> i64 + // CHECK: alignment = 16 + // CHECK: bitsize = 128 + // CHECK: preferred = 32 + "test.data_layout_query"() : () -> i128 + "test.maybe_terminator"() : () -> () + }) { dlti.dl_spec = #dlti.dl_spec< + #dlti.dl_entry : vector<2xi32>>, + #dlti.dl_entry : vector<2xi32>> + >} : () -> () + return +} + +func @floats() { + "test.op_with_data_layout"() ({ + // CHECK: alignment = 8 + // CHECK: bitsize = 32 + // CHECK: preferred = 8 + "test.data_layout_query"() : () -> f32 + // CHECK: alignment = 16 + // CHECK: bitsize = 80 + // CHECK: preferred = 16 + "test.data_layout_query"() : () -> f80 + "test.maybe_terminator"() : () -> () + }) { dlti.dl_spec = #dlti.dl_spec< + #dlti.dl_entry : vector<1xi32>>, + #dlti.dl_entry : vector<1xi32>> + >} : () -> () + "test.op_with_data_layout"() ({ + // CHECK: alignment = 8 + // CHECK: bitsize = 32 + // CHECK: preferred = 16 + "test.data_layout_query"() : () -> f32 + // CHECK: alignment = 16 + // CHECK: bitsize = 80 + // CHECK: preferred = 32 + "test.data_layout_query"() : () -> f80 + "test.maybe_terminator"() : () -> () + }) { dlti.dl_spec = #dlti.dl_spec< + #dlti.dl_entry : vector<2xi32>>, + #dlti.dl_entry : vector<2xi32>> + >} : () -> () + return +} diff --git a/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir b/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir --- a/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir +++ b/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir @@ -7,6 +7,27 @@ // ----- +// expected-error@below {{expected a dense i32 elements attribute}} +module attributes {dlti.dl_spec = #dlti.dl_spec< +#dlti.dl_entry : vector<2xi64>>> +} {} + +// ----- + +// expected-error@below {{expected 1 or 2 elements}} +module attributes {dlti.dl_spec = #dlti.dl_spec< +#dlti.dl_entry : vector<3xi32>>> +} {} + +// ----- + +// expected-error@below {{preferred alignment is expected to be greater than or equal to the abi alignment}} +module attributes {dlti.dl_spec = #dlti.dl_spec< +#dlti.dl_entry : vector<2xi32>>> +} {} + +// ----- + // expected-error@below {{the 'test' dialect does not support identifier data layout entries}} "test.op_with_data_layout"() { dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry,